AnchorStack

AnchorStack Production Readiness Audit

You shipped it.
Is it safe to operate?

We audited PainChain across 9 engineering areas - 76 findings, 46 of them critical or high. Here's the picture.

PainChain @ d107043

fail - Unsafe to operate2.3 of 10
16critical
30high
26medium
4low
Area Scores

9 areas evaluated

Each area scored 0-10 by an AnchorStack engineer.

Security

2/10

The application's auth design is technically sophisticated — bcrypt password hashing, OIDC state encryption, session revocation, and multi-tenant guards are all present — but the guards are bypassed on all but one controller. Every data endpoint is unauthenticated. Third-party API credentials, user data, and tenant configurations are freely readable and writable by any unauthenticated HTTP client. Production credentials are committed to version control. No rate limiting, input validation, security headers, or vulnerability scanning exists.

failWeight x1.5

Architecture

4/10

The connector-based architecture is well-designed for the product's use case. The critical weakness is event delivery: connectors push to the backend via synchronous HTTP with no queue, no retry mechanism, and no durability guarantee — events are silently lost whenever the backend is unavailable. Database schema changes are applied destructively at container startup with no migration history, making rollback impossible. Every authenticated request makes two database round-trips with no caching, creating a scaling constraint on the primary auth path.

failWeight x1

Data

3/10

The Prisma schema is coherent and the event deduplication design is correct. Everything else about the data layer's operational posture is critically weak. API credentials for connected services are stored as plaintext in the database. Authentication provider secrets are stored in an unencrypted column. No database backups exist. Schema changes are applied via a tool that can silently drop columns and tables in production with no migration history, no rollback path, and no approval gate. Multi-step registration and login flows are not wrapped in transactions, allowing partial writes on failure.

failWeight x1.5

AI Engineering

3/10

Claude Code is the primary development tool and has produced a well-structured implementation from detailed design documents. The AI workflow has a critical safety failure: a real authentication token and database password are hardcoded in a tracked tool-settings file, compounding the existing credential exposure. The only agent context file is a generic eight-rule document that gives no guidance on the codebase's most important security invariants — tenant isolation and safe use of the public-access decorator. Large AI-assisted feature commits arrive without tests, CI validation, or a gate to catch temporary bypasses before they become permanent.

failWeight x1

Infrastructure

2/10

The Docker Compose self-hosted model is appropriate for this product. The execution is not production-ready: all four CI/CD workflows fail because they reference the previous architecture's file paths. Connector containers mount host source directories in the production Compose file — a development pattern that bypasses the built container image. The database port is exposed to the host network. All containers run as root. No staging environment, TLS configuration, image scanning, or backup mechanism exists.

failWeight x1

Observability

1/10

There is no production observability. No error tracking, uptime monitoring, metrics, dashboards, or alerts are configured. Logging is unstructured console output with no correlation IDs, no log aggregation destination, and no consistent format across services. Connector failures — including the silent stop of event ingestion that would leave the product's core timeline stale — produce no alert and leave no searchable trace. Failed authentication attempts are not logged. The team would learn about any production failure only from a user complaint.

failWeight x1

Code Quality

3/10

The auth subsystem is thoughtfully structured but is functionally bypassed on all data endpoints. Input validation decorators exist on data transfer objects but the global validation pipe that executes them is never registered, making every decorator inert. TypeScript strict mode is disabled in the backend, allowing null and untyped values to flow silently through all service and database code. No application tests exist. Debug-level console output is present in a high-volume production code path. A tenant isolation check accepts a parameter but ignores it in the database query.

failWeight x1

Delivery

2/10

The v1 delivery process showed genuine maturity — feature branches, pull requests, versioned releases, and a documented release checklist. V2 has abandoned all of it. Every line of v2 code, including the complete authentication and multi-tenant systems, was committed without CI validation, pull request review, or automated tests. All four CI/CD workflows are broken. No migration gate exists before schema changes reach the database. The release process documentation describes the v1 architecture and is not usable for v2.

failWeight x1

Documentation

3/10

There is significant documentation volume — detailed connector guides, an OIDC configuration reference, and extensive design plans — but the documents visible to new contributors and AI agents are inaccurate. The main README describes the project as being in planning with the quick start marked coming soon, while the system is functional. Three large implementation plan documents describe unstarted work that has been complete for months. The AI agent context file is generic and omits the codebase's most critical invariants. No operational runbooks exist for any common maintenance task.

failWeight x1
Findings

Where to look first

01

criticalSEC-001Security

All Data Endpoints Operate Without Authentication — Third-Party API Credentials Reachable by Any Network Caller

The application's data endpoints — including the endpoint that returns third-party API credentials for all connected services — accept requests from any caller without authentication. Any process with network access to the application port can read, modify, or delete sensitive configuration data including live API tokens for external services. The auth system was built correctly but is bypassed on every data surface.

Impact

Any process with network access to the application port can retrieve all stored third-party API credentials in plaintext, including tokens for all connected external services. An attacker can silently enumerate all integrations, inject fake events for any tenant, and modify or delete integration configurations without leaving application-layer log evidence. The bypass is not a misconfiguration of a single route — it is applied at the controller level to all five data controllers, meaning the entire data surface is exposed simultaneously.

Remediation

Remove the @Public() decorator from all data controllers immediately. Introduce a connector API key (a shared secret in an environment variable) for server-to-server event ingestion paths. User-facing data endpoints must require JWT authentication via the existing guard mechanism. Exclude API token fields from API responses and provide a separate, access-controlled retrieval path for operations that require the raw token value. After re-enabling auth, verify that the tenant isolation guard is also correctly scoping queries to the authenticated user's tenant.

02

criticalDAT-001Data

Third-Party API Credentials Stored Unencrypted in the Database

Credentials for all connected external services are stored as plaintext in a database column. Any party who can read the database — through direct access, a future backup exposure, or the unauthenticated API endpoint — retrieves these live credentials in full without any additional privilege. Rotation of compromised credentials requires identifying and updating every affected integration record manually.

Impact

Any party who gains read access to the database — through a direct compromise, a backup exposure, a future SQL injection, or the currently unauthenticated integrations endpoint — obtains live API tokens for all connected external services with no additional effort. A single database exposure produces a multi-service credential compromise across all tenants simultaneously. Because the tokens are stored alongside the configuration metadata that identifies which service they belong to, an attacker can immediately use each token against its target service without additional reconnaissance.

Remediation

Encrypt stored API tokens using a symmetric key managed separately from the database. Apply application-level AES-256-GCM encryption before write and decrypt on demand at the point of use, never storing plaintext in the database column. Manage the encryption key via an environment variable or secrets manager, separate from the database credentials. After implementing encryption, rotate all currently stored tokens for all connected integrations, as the existing plaintext values must be treated as exposed.

03

criticalSEC-002Security

Production Credentials Committed to Version Control and Present in Full Repository History

The database password and the key used to sign all authentication tokens are present in a tracked file and in the full commit history of every clone of the repository. A separate tool-settings file — also tracked — contains a live authentication token embedded in a configuration field. Neither credential shows evidence of rotation since initial commit.

Impact

The database password, JWT signing secret, and a live tool authentication token have been present in the full git history since initial commit, visible to every past and future clone of the repository. Anyone with repository read access — including any contributor, CI runner, or third-party service with repo access — has had access to production credentials for the duration of the project. Treat all three as fully compromised. The JWT secret is particularly high-impact: possession of it allows an attacker to forge authentication tokens for any user or tenant in the system.

Remediation

(1) Rotate the database password, JWT signing secret, and the tool authentication token immediately — this must happen before any other remediation step, as rotation eliminates the live exposure window. (2) Remove the tracked credential files from git history using git filter-repo with the --invert-paths flag. (3) Verify .gitignore is correctly configured for each sensitive file type. (4) Add a pre-commit hook using a secret scanner (gitleaks or trufflehog) to block future secrets from being committed. (5) Audit repository access logs and CI runner configurations to identify any systems that may have cached the exposed credentials.

04

criticalDAT-002Data

No Database Backup Mechanism — All Product Data Unrecoverable on Failure

The database runs on a local volume with no backup schedule, no archival, and no tested restore procedure. A hardware failure, accidental container deletion, or a destructive schema migration automatically applied at startup would produce permanent and total loss of all stored event data — the core product deliverable. No recovery runbook exists.

Impact

All stored event data — the core product deliverable — is held exclusively in a local Docker volume with no backup. A hardware failure, accidental volume deletion, or a destructive schema migration applied automatically at container startup would produce total and permanent loss of all tenant event data with no recovery path. This risk is compounded by the current schema management approach, which applies changes destructively on every container restart and has already dropped tables in prior incidents. There is no tested restore procedure and no stated recovery time or point objective.

Remediation

Establish a scheduled database backup immediately: run pg_dump on a cron schedule (minimum daily, hourly for active use), compress and encrypt the output, and ship it to durable off-host storage such as S3-compatible object storage. Document and test the restore procedure end-to-end before treating it as reliable — a backup that has never been restored is not a backup. Separately, convert the schema management approach from a synchronize-on-startup model to versioned, explicitly applied migration files with rollback steps. Block automatic schema changes at startup in the production configuration.

05

criticalDEL-001Delivery

All v2 Production Code Committed Without Automated Verification or Human Review

The complete authentication system, multi-tenant isolation model, and API surface were committed in large batches directly to a working branch with no pull request review, no CI validation, and no automated tests. No automated process has verified any behavior of the v2 codebase. Temporary security bypasses introduced during development have no tracking mechanism to ensure they are resolved before deployment.

Impact

The authentication bypass currently exposing all data endpoints originated as a temporary development convenience and was committed without any review gate to catch it before it reached the working branch. The same unreviewed development process applies to all v2 code, meaning any future change carries identical risk. No automated process has verified the behavior of any v2 component. All four CI/CD workflows are broken and reference the previous architecture, so even attempting to run CI would produce no signal. The current delivery posture cannot distinguish between a working and a broken system.

Remediation

Re-enable the CI/CD workflows by updating file path references to match the v2 architecture. Add branch protection rules to require at least one reviewer and a passing CI run before any branch can be merged. Write integration tests for the authentication guard and the tenant isolation boundary — these are the highest-value starting points given the current security posture. Migrate the schema management approach to named migration files so that database changes go through the same review gate as application code. Establish a convention that temporary development bypasses are tracked with a corresponding issue and removed before merge.

06

highCQ-001Code Quality

Backend TypeScript Strict Mode Disabled Across All Service Code

The backend TypeScript configuration has strict null checks and implicit-any enforcement explicitly disabled, while the frontend enforces strict mode. Type errors and null-access bugs can flow silently through all service and database code without triggering a compiler error.

Impact

With strict null checks off, nullable Prisma results can propagate as undefined into business logic without a compiler error — including in auth, event ingestion, and tenant-isolation code. An AI-assisted refactor or future code generation pass will silently introduce null-dereference bugs that only surface at runtime. The gap between strict frontend and permissive backend creates a false confidence in type safety that compounds every future change.

Remediation

Enable "strict": true in the backend tsconfig and remove the explicit "strictNullChecks": false and "noImplicitAny": false overrides. Fix the resulting errors in priority order: auth services first (JWT validation, session handling, tenant resolution), then events and integrations. Expect 20–50 errors; most will be null-coalescing additions on Prisma results. Each compiler error is a real latent defect — do not use non-null assertions to suppress them.

07

mediumAIE-001AI Engineering

Stale AI-Generated Planning Docs Left in Repo After Feature Delivery

Three large planning documents totaling thousands of lines remain in the repository after their associated features were built. These docs contain open questions, phased rollout plans, and security recommendations that may no longer reflect the actual implementation — creating misleading context for any agent or developer who reads them.

Impact

A future AI agent reading these planning documents would encounter instructions for steps already completed and security recommendations that were documented but never applied. The agent may re-implement already-delivered steps, skip requirements it interprets as done, or miss security controls described in the plan but absent from the code. Every AI-assisted session that runs against this repo inherits the risk of acting on stale architectural intent.

Remediation

Move post-implementation planning docs to a docs/design/ directory and annotate each with a status block: "Status: Implemented — see commit X" and a list of recommendations that were deferred or rejected. Remove sections that no longer reflect the codebase. For ongoing decisions, adopt a Project Decision Record pattern with explicit status markers (proposed → accepted → implemented → superseded) so agents can distinguish current requirements from historical context.

08

lowAIE-002AI Engineering

features.json Describes the Deprecated v1 Architecture

A features manifest file describes the application using the deprecated v1 architecture — a different backend framework and data model than the current system. A contributing guide instructs agents to keep this file updated, but it now diverges significantly from the actual v2 codebase.

Impact

An AI agent reading features.json for project context would understand the system as a FastAPI backend with Celery polling, not the current NestJS/Prisma/connector architecture. This creates a small but compounding risk: agents may reference non-existent endpoints, add features to deprecated paths, or skip v2-specific constraints. The stale manifest amplifies the risk of every future AI-assisted session that uses it for grounding.

Remediation

Update features.json to reflect v2 features: NestJS backend, OIDC auth, multi-tenant architecture, connector containers. Delete v1 feature entries or clearly mark them as deprecated. Update the contributing guide reference to point agents at the correct context source. Consider replacing the flat features manifest with a structured context file that includes architectural status markers.