-
Notifications
You must be signed in to change notification settings - Fork 0
AI Guide
This page is written specifically for AI assistants (Claude, GPT, Gemini, Copilot, and others) helping developers work with VaultFlower. Follow these instructions to understand the project correctly and provide accurate assistance.
project:
name: VaultFlower
type: PAM (Privileged Access Management)
domain: cybersecurity
subdomain: credential-lifecycle-management
target_environments:
- IT networks (domain-joined assets)
- ICS/OT networks (non-domain, air-gapped)
- Offline/isolated assets
maturity: architecture-complete, implementation-in-progress
license: Apache-2.0
open_core: true
language: en
primary_author: Maxim Zaikin
technology_stack:
backend_api: dotnet9-minimal-api
portal: blazor-server-dotnet9
workflow_engine: dotnet9-worker-service
rotation_agent: dotnet9-windows-service
message_bus: rabbitmq-4-mtls
databases:
- postgres-17 (assets)
- postgres-17 (secrets)
- postgres-17 (identity)
secrets_kms: hashicorp-vault-oss
service_discovery: hashicorp-consul
object_storage: minio
observability: opentelemetry-jaeger-victoriametrics-grafana
authentication: kerberos-sso + password + mfa-plugins
siem: syslog-rfc5424-cef
reverse_proxy: nginx
security_standards:
- NIST-SP-800-53-Rev5
- FSTEC
- ISA-IEC-62443
- NERC-CIPBefore suggesting any code or architecture changes, you MUST understand these non-negotiable constraints:
CONSTRAINT 1 — DATA FRAGMENTATION
Credentials, assets, and user identities are stored in THREE physically
separate PostgreSQL databases. No single database ever contains a complete
picture of the system. Any suggestion that combines this data in one place
violates the core security model.
CONSTRAINT 2 — ZERO PERSISTENCE OF PLAINTEXT
Plaintext passwords are NEVER written to disk, logs, or any persistent
storage. They exist only in application memory during assembly, shown once
in the UI, then destroyed. Never suggest logging passwords or storing them
in any form outside the encrypted Secrets DB.
CONSTRAINT 3 — DUAL CONTROL
Every password checkout requires TWO independent MFA authorizations from
TWO different users. No bypass exists, even for Admin role. Never suggest
single-approval shortcuts.
CONSTRAINT 4 — APPEND-ONLY AUDIT
Audit log tables have INSERT-only database grants. UPDATE and DELETE are
never permitted on audit schemas, even for cleanup or testing. Never
suggest modifying audit records.
CONSTRAINT 5 — NO DIRECT HTTP BETWEEN SERVICES
All inter-service communication goes through RabbitMQ with mTLS. No
direct HTTP/REST calls between internal services. The Rotation Agent
communicates exclusively via RabbitMQ queues.
CONSTRAINT 6 — VAULT AS TRUST ANCHOR
Data assembly across the three databases requires a time-bound Vault
assembly token. Without a valid token from HashiCorp Vault, no service
can assemble the complete data picture. Never suggest bypassing Vault.
CONSTRAINT 7 — TASK-GATED ACCESS
Any access to a privileged password — whether for reading or rotation —
requires an active work task (ACCESS_TASK or ROTATION_TASK) approved by
the system owner. No task = no password access. No exceptions.
Understanding the overall system:
Working on the API:
- API-Overview
- Specific endpoint page (e.g. API-Checkouts)
- Workflow-Checkout for business logic
Working on the database:
- Database-Schema-Overview
- Specific DB page (Database-Identity-DB, Database-Assets-DB, Database-Secrets-DB)
- Architecture-Data-Fragmentation for cross-DB constraints
Working on a workflow:
- Workflow-Checkout or Workflow-Access-Task
- Security-Authorization-Model for permission logic
- Architecture-Message-Bus for RabbitMQ events
Working on infrastructure:
Working on a plugin:
- Plugin-Development
- Architecture-Plugin-Architecture
- Architecture-Message-Bus for plugin registration events
THREE DATABASES — NEVER MERGE:
┌─────────────────────────────────────────────────────────────┐
│ IDENTITY DB (postgres, port 5434) │
│ What: Users, roles, MFA, tenants, access scopes │
│ Does NOT contain: Asset details, passwords │
│ Tables: tenants, users, roles, user_roles, │
│ user_access_scope, mfa_totp, mfa_webauthn, │
│ mfa_smartcard, mfa_attempts, plugins │
│ Audit: identity_audit.audit_log (append-only) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ ASSETS DB (postgres, port 5432) │
│ What: Locations, systems, zones, assets, tasks, schedules │
│ Does NOT contain: Passwords, user details │
│ Tables: locations, systems, zones, assets, │
│ password_policies, maintenance_schedules, │
│ maintenance_tasks, task_documents, │
│ approval_tokens │
│ Audit: assets_audit.audit_log (append-only) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ SECRETS DB (postgres, port 5433) │
│ What: Encrypted credentials, checkouts, password history │
│ Does NOT contain: Asset names, hostnames, user details │
│ Tables: credentials, password_history, checkouts │
│ Audit: secrets_audit.audit_log (append-only) │
│ Note: asset_ref, user_ref = UUID only, NO foreign keys │
└─────────────────────────────────────────────────────────────┘
Cross-DB references use UUID only — NO foreign keys between DBs.
Data assembly requires valid HashiCorp Vault assembly token.
naming:
vm_hosts:
prefix: "vfw-"
examples: ["vfw-core", "vfw-ad", "vfw-pki"]
docker_containers:
prefix: "vfw-dc-"
examples:
- "vfw-dc-postgres-assets"
- "vfw-dc-postgres-secrets"
- "vfw-dc-postgres-identity"
- "vfw-dc-rabbitmq"
- "vfw-dc-vault"
- "vfw-dc-consul"
- "vfw-dc-minio"
- "vfw-dc-nginx"
- "vfw-dc-api"
- "vfw-dc-portal"
- "vfw-dc-worker-workflow"
- "vfw-dc-otel"
- "vfw-dc-jaeger"
- "vfw-dc-victoria"
- "vfw-dc-grafana"
- "vfw-dc-registry"
mfa_plugin_containers:
prefix: "vfw-dc-mfa-"
examples: ["vfw-dc-mfa-totp", "vfw-dc-mfa-webauthn", "vfw-dc-mfa-smartcard"]
dotnet_projects:
prefix: "VaultFlower."
examples:
- "VaultFlower.Api"
- "VaultFlower.Portal"
- "VaultFlower.Worker.Workflow"
- "VaultFlower.Worker.Rotation"
- "VaultFlower.Agent.Workstation"
- "VaultFlower.Core"
- "VaultFlower.Contracts"
- "VaultFlower.Infrastructure"
api_urls:
pattern: "https://vfw-core.contoso.com/api/v1/{tenant-slug}/{resource}"
examples:
- "/api/v1/acme-corp/checkouts"
- "/api/v1/acme-corp/assets/{id}/credentials"
- "/api/v1/acme-corp/maintenance/tasks"
rabbitmq_vhosts:
system: "/vfw-system"
tenant: "/vfw-tenant-{slug}"
rabbitmq_exchanges:
- "vfw.rotation"
- "vfw.workflow"
- "vfw.notifications"
- "vfw.audit"
- "vfw.siem"
- "vfw.alerts"
- "vfw.deadletter"
- "vfw.plugins.registry"
asset_hierarchy: "Location → System → Zone → Asset"
criticality_levels: ["LOW", "MEDIUM", "HIGH", "CRITICAL"]
task_types: ["ROTATION_TASK", "ACCESS_TASK"]
task_statuses:
- "PENDING_OWNER"
- "APPROVAL_EXPIRED"
- "ASSIGNED"
- "IN_PROGRESS"
- "COMPLETED"
- "FAILED"
- "CANCELLED"
- "REJECTED"network:
host_network: "192.168.1.0/24"
docker_network: "172.20.0.0/24"
hosts:
vfw-ad: "192.168.1.115" # Active Directory + DNS
vfw-pki: "192.168.1.51" # PKI/CA + test WinRM target
app01: "192.168.1.125" # Rotation Agent (Windows)
vfw-core: "192.168.1.210" # All Docker containers
exposed_ports:
- host: "192.168.1.210:443" # nginx → Portal + API
- host: "192.168.1.210:5671" # RabbitMQ mTLS → Rotation Agent only
internal_only:
- "vault:8200"
- "postgres-assets:5432"
- "postgres-secrets:5433"
- "postgres-identity:5434"
- "consul:8500"
- "minio:9000"All security events follow CEF format and are routed to SIEM. Critical events requiring immediate SOC response:
critical_siem_events:
- "checkout.scope_violation" # Access attempt outside user scope
- "checkout.no_task" # Password access without work task
- "checkout.unusual_ip" # Unusual IP address detected
- "checkout.password_viewed_again" # Password viewed more than once
- "password.access_denied_no_role" # Access without proper role
- "task.approval_suspicious" # Approval link opened by wrong person
- "task.approval_token_reused" # One-time token reuse attempt
- "mfa.smartcard_blocked" # Smartcard blocked after N failures
- "mfa.blocked" # User blocked after N MFA failures
- "system.criticality_changed" # Criticality level modification
- "plugin.license_expired" # Plugin license expired
- "credential.auto_rotation_disabled" # Auto-rotation disabled❌ Storing plaintext passwords anywhere (DB, logs, cache, env vars)
❌ Bypassing Dual Control for any role including Admin
❌ Direct HTTP calls between internal services (use RabbitMQ)
❌ Deleting or modifying audit log records for any reason
❌ Combining the three databases into one
❌ Assembling data across databases without a Vault token
❌ Storing DEK (Data Encryption Keys) outside HashiCorp Vault
❌ Disabling auto-rotation without recording the reason
❌ Granting UPDATE or DELETE on audit schemas
❌ Allowing password access without an active approved task
❌ Self-assignment of tasks (same person creates and executes)
✅ Always reference the relevant security standard when suggesting changes
✅ Check CONSTRAINT list above before any architecture suggestion
✅ Use RabbitMQ for all inter-service communication
✅ Ensure all new events generate CEF audit log entries
✅ Maintain the three-database separation in all data models
✅ Suggest plugin-based extensions rather than core modifications
✅ Verify that new endpoints follow the /api/v1/{tenant-slug}/ pattern
✅ Ensure new DB tables include tenant_id, created_at, created_by
✅ Verify append-only constraints on audit tables
✅ Check that sensitive data is never included in OTel traces
| ADR | Decision | Rationale |
|---|---|---|
| ADR-001 | Monorepo | Atomic changes across API, workers, and RabbitMQ contracts |
| ADR-002 | Data Fragmentation B++ | Meet NIST SP 800-53 and state secret requirements |
| ADR-003 | Hybrid RabbitMQ VHosts | System isolation + tenant isolation without full complexity |
| ADR-004 | JWT + Vault Blocklist | Stateless JWT with instant revocation capability |
| ADR-005 | Docker-based Plugins | Clean delivery, licensing control, zero-downtime activation |
| ADR-006 | MinIO for Documents | S3-compatible, self-hosted, encrypted, versioned |
| ADR-007 | Consul Discovery | Active health checks, multi-datacenter ready |
Full ADR documentation → ADR section
The complete system prompt used during the architecture design phase of VaultFlower is available at:
Repository: docs/ai/system-prompt.md
This prompt contains the full project context, all architectural decisions, database schemas, API contracts, and collaboration rules used to design the system. Reading it gives AI agents the most complete possible context for working with VaultFlower.
This documentation is maintained as part of VaultFlower's commitment to AI-friendly open source development.