Files
VolcanicCore/CLAUDE.md

6.8 KiB

VolcanicCore — project context for Claude sessions

VolcanicCore is a self-hosted N8N-style workflow engine (C# backend + React frontend). Operator draws a directed graph of nodes (triggers → actions → terminals) in a browser canvas; each workflow can be activated independently. When active, trigger nodes subscribe/listen and each event fires one execution through the graph.

Documents to read first

  • Design spec — docs/superpowers/specs/2026-08-28-volcaniccore-workflow-engine-design.md. The whole architecture (execution model, extension contracts, webhook mechanics, persistence, deploy shape). Read this before writing plans or code.
  • Plan 1 (backend foundation, executed) — docs/superpowers/plans/2026-08-28-plan-1-backend-foundation.md. Shows the working style and the file structure conventions.
  • Follow-ups — docs/superpowers/followups.md. Cross-plan items surfaced during review that later plans must handle. Read before starting a plan; extend as new items surface.

Current status

Plan 1 (backend foundation) shipped. Head commit at plan close: 86bf173. dotnet build clean, dotnet test 20/20.

What's done:

  • ASP.NET Core 9 monolith. Four projects: VolcanicCore.Core (contracts), .Persistence (SQLite, migrator, encryption, repos), .Api (endpoints, auth, registries), VolcanicCore.Tests (xUnit + WebApplicationFactory).
  • Admin cookie auth (BCrypt, ADMIN_PASSWORD env), sessions endpoints.
  • SQLite with hand-rolled versioned migrator (3 migrations: admin_config, connections, workflows).
  • AES-GCM encryption for connection secrets (key from ENCRYPTION_KEY env or /data/.enc-key).
  • Extension contracts: INodeType / IActionNode / ITriggerNode / IConnectionProvider in .Core.
  • DI-collected NodeRegistry and ConnectionProviderRegistry.
  • REST endpoints: session, discovery (empty in Plan 1), connections CRUD, workflows CRUD + activate/deactivate.

What's next: Plan 2 — the workflow engine itself. Not yet written. When authored, it will cover:

  • Executions + node_executions tables (Migration 004 + 005).
  • Executor — in-degree scheduler, fan-out, failure propagation per §4 of the design spec.
  • WebhookRouter + POST /wh/{workflow-id}/{*path} — see §5 of the spec.
  • TriggerHost lifecycle — start triggers on activation, dispose on deactivation.
  • NATS IConnectionProvider + all five nodes: NATS Hook, Webhook, PythonTransform (IronPython 3), WebResponse, NATS Publish.
  • Manual test-run endpoint.
  • Retention BackgroundService.
  • Discovery endpoints will start returning real node types + providers once these are DI-registered.

Plans 3 (React SPA) and 4 (Coolify Dockerfile + deploy) follow.

Invariants (do NOT relearn from scratch)

  • Git commit identity. The repo has no configured identity. Every commit must pass -c user.email="claude@volcanic" -c user.name="Claude":
    git -c user.email="claude@volcanic" -c user.name="Claude" commit -m "..."
    
  • Working branch. main. The user opted in to this at project start. No feature branches unless requested.
  • Test parallelism is disabled at the assembly level. See the [assembly: CollectionBehavior(DisableTestParallelization = true)] attribute at the top of tests/VolcanicCore.Tests/WebFactory.cs. Multiple WebFactory instances share the process; pre-Configuration.Bind env-var reads made parallel classes flaky. Do not re-enable parallelism without a redesign.
  • Cookie authentication is in the shared framework. Do NOT add Microsoft.AspNetCore.Authentication.Cookies as a PackageReference. The last standalone version on NuGet is 2.3.0 (ASP.NET Core 2.x, 2019). .NET 9's Microsoft.AspNetCore.App shared framework provides the cookie-auth types with no PackageReference.
  • Program.cs env-var loop honors pre-set config. In tests, WebFactory.ConfigureWebHost uses builder.UseSetting(...) to inject DataDirectory and AdminPassword. The env-var loop in Program.cs skips keys already set by upstream sources (if (!string.IsNullOrEmpty(builder.Configuration[prop])) continue;). Do not remove this check.
  • Migration001Initial, 002Connections, 003Workflows are registered in the Migrator factory in Program.cs. Add new migrations to the same array in version order.
  • AdminBootstrap stores admin.password_hash_source in plaintext by design (see the comment in AdminBootstrap.cs) — it is the change-detector for the env-provided ADMIN_PASSWORD. Do not "fix" this by hashing the source. Encryption at rest for admin_config is a Plan 2 follow-up.
  • IConnectionSecretPolicy in Plan 1 is HardcodedSecretPolicy (fixed field-name set). Plan 2 replaces it with a schema-driven implementation that reads secretFields off each registered provider's ConfigSchema. Do not extend the hardcoded set further — replace instead.

Working style

  • Design with superpowers:brainstorming, plan with superpowers:writing-plans, execute with superpowers:subagent-driven-development. This is the tempo Plan 1 shipped on.
  • Split large scopes into multiple plans (Plan 1 was foundation, Plan 2 is engine, Plan 3 is frontend, Plan 4 is deploy). Each plan should end in a testable state.
  • TDD in each task: write the failing test, watch it fail, implement, watch it pass, commit. Migrator, connection CRUD, workflow CRUD all follow this pattern — see their commits for examples.
  • Two-stage review per task: spec-compliance reviewer (haiku), then code-quality reviewer (sonnet). For crypto or wire-format work, escalate quality-reviewer to opus. For pure interface/type tasks, one combined reviewer is fine.
  • Follow-ups. When a reviewer surfaces a real concern that isn't in scope for the current task, add it to docs/superpowers/followups.md with which plan should handle it. Do not silently drop review feedback.
  • Commit style. Conventional Commits (feat(scope):, fix(scope):, chore:, docs:). One meaningful change per commit; TDD tasks land one commit per task at the end (test + impl together).

How to run

# Build + test
dotnet build
dotnet test

# Live server (boot with a real SQLite DB)
DATA_DIRECTORY=$(pwd)/_smoke ADMIN_PASSWORD=hunter2 \
  dotnet run --project src/VolcanicCore.Api --urls http://127.0.0.1:5099
# Then: curl -c jar -X POST -H 'content-type: application/json' \
#         -d '{"password":"hunter2"}' http://127.0.0.1:5099/api/session
# And follow up with -b jar for authenticated calls.

dotnet run --project X sets the content root to X's directory, so DATA_DIRECTORY=./relative lands under src/VolcanicCore.Api/ — always pass an absolute path.

Deploy target

Coolify — env vars COOLIFY_URL, COOLIFY_KEY, GIT_URL, GIT_USER, GIT_KEY are available in the container. Actual container packaging + Coolify wiring is Plan 4. Global CLAUDE.md rule applies: fire-and-forget deploys via the v4 API, never block on build.