Skip to content

feat(domain): add policy-driven supply chain security subsystem#527

Open
arielshad wants to merge 37 commits intomainfrom
feat/supply-chain-security
Open

feat(domain): add policy-driven supply chain security subsystem#527
arielshad wants to merge 37 commits intomainfrom
feat/supply-chain-security

Conversation

@arielshad
Copy link
Copy Markdown
Contributor

Summary

Adds a phased, policy-driven supply chain security subsystem that constrains agent execution, validates dependency and release-integrity risk, and exposes security state across CLI, CI, and the Control Center.

  • TypeSpec-first domain models: SecurityMode, SecurityPolicy, SecurityEvent, SecurityFinding, DependencyRiskReport, ReleaseIntegrityReport enums and entities with generated types as single source of truth
  • Policy engine: Hybrid file (shep.security.yaml) + SQLite settings persistence, strict-wins merge precedence, deterministic evaluation across CLI/CI/runtime
  • Runtime guardrails: Pre-execution security checks in LangGraph executeNode() — classifies actions into categories (dependency install, CI/release modification, publish), applies deny/approval_required/warn/allow dispositions per policy
  • CLI enforcement: shep security enforce command with human-readable and structured JSON/YAML output, non-zero exit on enforce-mode failures
  • Dependency risk evaluator: Lockfile consistency, dependency source type, lifecycle scripts, allowlist/denylist, version-range policy — all local heuristics, no external services
  • Release integrity evaluator: CI workflow validation, secrets handling, provenance configuration, semantic-release verification
  • GitHub governance audit: Branch protection, CODEOWNERS, workflow governance checks via existing gh CLI (audit-only, no mutations)
  • CI integration: Security enforcement job in GitHub Actions, policy scaffold for new repositories
  • Web UI surfaces: SecurityPanel, SecurityBadge components with Storybook stories; Control Center security overlay; Settings page Security tab with mode selector, policy source, findings
  • Full test coverage: 177 security-specific tests across 17 test files; 6181 total tests passing across 452 files

Key Design Decisions

Decision Choice Rationale
Default mode Advisory Exposes findings without breaking existing repos
Policy storage Hybrid file + SQLite Rules reviewable in git; state persisted locally
Runtime actions Approval gate + deny list Reuses HITL pattern; fails closed on denied actions
Dependency risk Local heuristics only Deterministic, offline-compatible, no external deps
GitHub governance gh audit only Current architecture has no GitHub App support
Publish blocking All publish paths No bypass allowed for dev or main publishes
Event retention 90-day default Useful audit trail without permanent archival

Architecture

The implementation spans all four Clean Architecture layers:

  • Domain: TypeSpec models → generated types, SecurityViolationError, SecurityConstraints interface
  • Application: 4 use cases (EnforceSecurity, EvaluateSecurityPolicy, GetSecurityState, RecordSecurityEvent), port interfaces (ISecurityPolicyService, ISecurityEventRepository)
  • Infrastructure: SecurityPolicyFileReader, SecurityPolicyValidator, SecurityPolicyService, SQLiteSecurityEventRepository, SecurityEventMapper, DependencyRiskEvaluator, ReleaseIntegrityEvaluator, GovernanceAuditor, 2 SQLite migrations
  • Presentation: CLI command, web server actions, React components with Storybook stories, i18n translations

Evidence

CLI

Evidence Description
Human-readable output shep security enforce showing Advisory mode, 8 findings, exit code 0
JSON output Structured output with policy snapshot, dependency/release/governance findings

Web UI

Evidence Description
Settings Security Tab Security mode selector, policy source, last evaluation, recent findings
Full Settings Page Security tab in navigation alongside all other settings sections
Control Center Feature canvas with supply chain security feature card

Storybook

Evidence Description
SecurityPanel - Mixed Findings High/Medium/Low severity badges with remediation text
SecurityPanel - No Findings Empty state
SecurityBadge - Advisory Yellow shield icon
SecurityBadge - Enforce Red shield-alert icon
SecurityBadge - Disabled Gray shield-off icon
Settings - Advisory with Findings Advisory mode with severity badges
Settings - Disabled Disabled mode state
Settings - Enforce Critical Enforce mode with critical finding

Tests

  • 177 security-specific tests across 17 test files (policy service, evaluators, use cases, runtime checks, CLI command, event persistence)
  • 6181 total tests passing across 452 test files

Test plan

  • 149 security unit tests pass (policy, evaluators, use cases, CLI, validator)
  • 16 runtime guardrail tests pass (classify actions, check dispositions across modes)
  • 49 release integrity and governance tests pass
  • 608 integration tests pass including security event persistence
  • 6181 total tests pass across 452 test files
  • All Storybook stories render correctly for SecurityPanel, SecurityBadge, SupplyChainSecuritySettingsSection
  • Build compiles without errors
  • Lint, format, and typecheck all pass

Built with Shep 🐑 Shep Bot

@arielshad arielshad force-pushed the feat/supply-chain-security branch from 1eb0ac9 to b314a3f Compare April 5, 2026 19:49
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 5, 2026

Dev Release Published

Artifact Version Install
npm 1.171.0-pr527.e2ee839 npm install -g @shepai/cli@1.171.0-pr527.e2ee839

Published from commit 41ce708 | View CI

arielshad and others added 28 commits April 6, 2026 14:34
Covers policy engine architecture, TypeSpec domain models, hybrid
policy storage, runtime guardrails, CLI enforcement, CI integration,
dependency risk evaluation, GitHub governance audit, web UI surfaces,
and release integrity enforcement across 13 key decisions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… chain security

34 tasks across 7 phases: domain models, policy engine, CLI enforcement,
runtime guardrails, GitHub governance audit, web UI surfaces, and CI integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Define SecurityMode, SecurityActionCategory, SecurityActionDisposition,
SecuritySeverity, DependencyRiskType, and ReleaseIntegrityCheckType enums
in tsp/common/enums/security.tsp. Define SecurityPolicy, SecurityEvent,
DependencyFinding, ReleaseIntegrityResult, EffectivePolicySnapshot and
supporting models in tsp/domain/entities/security.tsp. Add SecurityConfig
to Settings model with mode, lastEvaluationAt, and policySource fields.
Run tsp:compile to generate output.ts with all new types.
Migration 053 adds security_mode (TEXT NOT NULL DEFAULT 'Advisory'),
security_last_evaluation_at (TEXT), and security_policy_source (TEXT)
columns to the settings table.

Migration 054 creates the security_events table with id, repository_path,
feature_id, severity, category, disposition, actor, message,
remediation_summary, and created_at columns plus indexes on
(repository_path, created_at) and (feature_id).

Both migrations are idempotent and additive-only with no-op down().
Add SecurityConfig support to the settings persistence layer:
- Map security.mode/lastEvaluationAt/policySource to flat DB columns
- Default security.mode to Advisory in settings defaults factory
- Update SQLite repository INSERT/UPDATE for new security columns
- Add comprehensive mapper tests (toDatabase, fromDatabase, round-trip)
- Add defaults factory tests for SecurityConfig

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce the central ISecurityPolicyService port interface and its
infrastructure implementation. Includes security policy file reader
(shep.security.yaml via js-yaml), schema validator with fail-fast
semantics, and deterministic policy evaluator that merges global
settings defaults with repository policy using strict-wins precedence.
Also adds ISecurityEventRepository port interface for event persistence.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement SecurityEventRow mapper with toDatabase/fromDatabase functions
and SQLiteSecurityEventRepository with save, findByRepository, findByFeature,
deleteOlderThan (90-day retention), and count operations. All queries use
parameterized SQL. Includes mapper unit tests and repository integration tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Register ISecurityPolicyService, ISecurityEventRepository,
SecurityPolicyFileReader, and SecurityPolicyValidator in the
DI container. All security services follow existing factory
registration patterns for consistent resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add four use cases for the security subsystem:
- EnforceSecurityUseCase: orchestrates full enforcement flow
- EvaluateSecurityPolicyUseCase: wraps policy evaluation
- GetSecurityStateUseCase: returns security state for UI
- RecordSecurityEventUseCase: persists events with retention

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add createSecurityCommand() with enforce subcommand that evaluates
repository security posture via EnforceSecurityUseCase. Supports
--output json for CI consumption and --repo for custom paths. Exit
code 0 for pass, 1 for enforce-mode failure. Register all phase 3
services and use cases in the DI container.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add SecurityConstraints type and securityConstraints field to
AgentExecutionOptions. Create SecurityViolationError class for
policy violations. Add reusable validateSecurityConstraints()
function and integrate into Claude Code executor with Enforce
mode fail-closed and Advisory mode warning behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add securityMode and securityActionDispositions channels to
FeatureAgentAnnotation. Extend WorkerArgs with security fields
and parseWorkerArgs with --security-mode and --security-dispositions
CLI arg parsing. Thread security state into graph invoke calls.
Fix mock state objects in existing tests to include new channels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pass securityMode from settings to all 6 process spawn call sites
(create, start, resume, approve, reject, unblock) so the worker
process receives the configured security policy mode as a CLI arg.

Update IFeatureAgentProcessService interface and
FeatureAgentProcessService implementation to accept and forward
securityMode and securityActionDispositions spawn options.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add security-pre-check module with classifyNodeAction() to map graph
node names to SecurityActionCategory, and checkSecurityDisposition()
to evaluate the effective policy before agent execution.

Integrate into executeNode() in node-helpers.ts: denied actions throw
SecurityViolationError in Enforce mode, approval-required actions
trigger interrupt(), and Advisory mode logs warnings without blocking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
extend igithubrepositoryservice with auditrepositorygovernance method
and governancefinding type for branch protection and codeowners checks.
implement gh-cli-backed governance auditor that handles auth errors
gracefully as unknown findings. integrate governance audit into
enforcesecurityusecase as audit-only (per fr-15) so governance findings
are reported and persisted but never cause enforce-mode failures. add
governance section to cli output and i18n translations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add web UI components for supply-chain security observability:
- Security server actions (getSecurityState, enforceSececurity, updateSecurityMode)
- SecurityBadge component with mode-aware shield icon on feature nodes
- SecurityPanel collapsible drawer section with severity summary and event list
- SupplyChainSecuritySettingsSection with mode selector and findings display
- Integrate security section into settings page navigation and layout
- Thread securityMode through build-graph-nodes to feature node data
- Add security i18n keys to all locale web.json and cli.json files
- Fix .js import extension in security-violation.error.ts for Turbopack
- Add getSettings mock to start-feature and prd-approval integration tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add security-enforce parallel job to ci.yml that runs
shep security enforce --output json. Gate both release and
dev-release jobs on the security-enforce job passing.

Add scaffoldSecurityPolicy method to ISpecInitializerService
and SpecInitializerService that generates a baseline
shep.security.yaml with Advisory mode, default action
dispositions, and dependency/release rules with YAML comments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server actions were importing security use case classes directly which
caused Next.js turbopack to attempt bundling the entire node dependency
tree. Switch to type-only imports with string DI token resolution,
matching the pattern used by all other server actions. Add corresponding
string token registrations in the DI container.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Evidence covers all 7 phases of the 083-supply-chain-security feature:
- 120 security-specific unit tests passing (13 test files)
- 16 runtime guardrail tests passing
- 43 release integrity and governance tests passing
- 608 integration tests passing
- CLI enforce command with human and JSON output
- App settings page with security section rendering
- Storybook stories for SecurityPanel and SecurityBadge components
- Full test suite: 6181 tests passing across 452 test files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add missing security server action mock for Storybook to prevent
dynamic import failure in supply-chain-security-settings-section
stories. Import i18n singleton in preview.tsx to ensure translations
are available before stories render.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Recaptured all evidence files after fixing Storybook mock and i18n
initialization issues. Screenshots now show real component renders
instead of error pages. Test evidence uses targeted configs for
clean, focused output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Recaptured all 15 evidence files with improved quality:
- App screenshots now show real settings page with Security tab,
  security mode selector, and Control Center with feature cards
- Storybook screenshots now include full page with sidebar context
  instead of tiny clipped component-only captures
- Test outputs freshly captured from passing test runs
- CLI outputs show actual security enforce command results

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Why: buildGraphNodes accepted a securityMode option and feature-node
rendered SecurityBadge when data.securityMode was set, but get-graph-data
never forwarded security.mode from settings — so no badge ever appeared
on the live canvas despite the wiring existing end-to-end.

Adds 4 regression tests in build-graph-nodes.test.ts and a LESSONS.md
entry so the call site cannot silently drift again.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
arielshad and others added 2 commits April 6, 2026 14:39
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rebase onto main pulled in main's new IGitHubRepositoryService methods
(getAuthenticatedUser, checkPushAccess, forkRepository). The governance
audit commit's mock in enforce-security.use-case.test.ts was missing
these additions and broke typecheck.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@arielshad arielshad force-pushed the feat/supply-chain-security branch from 4ee3ded to 8338d20 Compare April 6, 2026 11:42
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 6, 2026

Dev Release Published

Artifact Version Install
npm 1.175.0-pr527.9ada632 npm install -g @shepai/cli@1.175.0-pr527.9ada632

Published from commit 8338d20 | View CI

Adds a master feature flag that makes the entire supply chain security
feature inert when off. Defaults to true to preserve current behavior.

Gates every surface the feature touches:
- Web canvas: get-graph-data skips passing securityMode so no badge renders
- Web Settings page: Security nav tab and section are hidden
- Agent ExecuteNode: resolveEffectiveSecurityMode forces Disabled so the
  pre-check becomes a no-op regardless of state.securityMode
- CLI: shep security enforce exits 0 with a flag-disabled note, honoring
  both settings and the SHEP_SUPPLY_CHAIN_SECURITY env var
- CI: security-enforce job reads SHEP_SUPPLY_CHAIN_SECURITY from repo vars
  so the flag can be flipped from one place

Why: the feature previously had no rollback path. The only way to disable
it was to set SecurityMode=Disabled in settings, which left the UI
surfaces, migrations, and enforcement wiring all in place. If any
component misbehaves in production there was no one-line escape hatch.
Now flipping featureFlags.supplyChainSecurity=false (or the env var in
CI) renders the feature fully inert.

Adds regression tests for every gate:
- Mapper round-trip for the new column (migration 056)
- CLI command gate via both settings and env var (5 new tests)
- resolveEffectiveSecurityMode helper (4 new tests)
- FeatureFlagsSettingsSection renders the new toggle
- Settings defaults include supplyChainSecurity=true

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 6, 2026

🔒 Security Issues Detected

Scanner Status Details
Gitleaks ❌ Failed Secret detection in git history
Semgrep ✅ Pass SAST for TypeScript/JavaScript

⚠️ Please review the failed checks above before merging.


🤖 Generated by CI Security Scan | View Details

The commit 1c6b476 on feat/messaging-remote-control contains a test
fixture with a fake API key that gitleaks flags. A follow-up commit
3173676 on the same branch already tried to fix it, and its fingerprint
is in .gitleaksignore — but the original commit is still reachable in
the git object graph, so gitleaks detect scanning the repo picks it up.
Adds the earlier fingerprint to the allowlist so it matches the already-
whitelisted replacement.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 6, 2026

Dev Release Published

Artifact Version Install
npm 1.175.1-pr527.ea242b8 npm install -g @shepai/cli@1.175.1-pr527.ea242b8

Published from commit fcf2ff8 | View CI

arielshad and others added 3 commits April 14, 2026 00:08
…urity

# Conflicts:
#	.github/workflows/ci.yml
#	.gitleaksignore
#	LESSONS.md
#	packages/core/src/domain/generated/output.ts
#	packages/core/src/infrastructure/di/container.ts
#	src/presentation/web/app/(dashboard)/get-graph-data.ts
#	src/presentation/web/app/build-graph-nodes.ts
#	src/presentation/web/components/features/settings/settings-page-client.tsx
#	tsp/domain/entities/index.tsp

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

🔒 Security Issues Detected

Scanner Status Details
Gitleaks ❌ Failed Secret detection in git history
Semgrep ✅ Pass SAST for TypeScript/JavaScript

⚠️ Please review the failed checks above before merging.


🤖 Generated by CI Security Scan | View Details

…s gitleaks

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

🔒 Security Issues Detected

Scanner Status Details
Gitleaks ❌ Failed Secret detection in git history
Semgrep ✅ Pass SAST for TypeScript/JavaScript

⚠️ Please review the failed checks above before merging.


🤖 Generated by CI Security Scan | View Details

…n stories

Co-Authored-By: Shep Bot <shep-agent@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

Dev Release Published

Artifact Version Install
npm 1.183.0-pr527.80e6e27 npm install -g @shepai/cli@1.183.0-pr527.80e6e27

Published from commit 10571d2 | View CI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant