Security at PlanVault

Last updated: May 11, 2026

PlanVault.ai is a hosted B2B SaaS platform for AI-agent orchestration operated by Bohdan Matviichuk (Polish JDG, ul. Dziewanny 21/19, 20-539 Lublin; NIP PL7123452217). This page describes the technical and organizational measures (TOMs) we apply to protect Customer Data, together with the shared-responsibility boundaries and the controls we are transparent about not yet having in place. It is written for security, procurement, and data-protection reviewers who need to decide whether PlanVault fits their risk posture.

The authoritative legal commitments on processing, confidentiality, security, and incident notification live in our Data Processing Agreement (https://planvault.ai/dpa). The current list of subprocessors is at https://planvault.ai/subprocessors. This Security page summarizes how those commitments are delivered in practice; where the two differ, the signed DPA (or, absent a signed agreement, the online DPA) controls.

Core posture: EU-based operator, primary hosting in Germany (AWS eu-central-1), encryption by default with per-tenant keys, bring-your-own-key (BYOK) for AI providers, GDPR Article 32 controls, GDPR Article 15 / 17 data-subject self-service, and an honest statement of which third-party certifications we hold today (none; see Section 15).

Questions: [email protected] is the dedicated inbox for vulnerability reports and security reviews. [email protected] is the preferred channel for GDPR / data-subject / breach notifications. [email protected] is the general platform inbox. All three route to the same operator for triage.

Summary of key points

Skim the summary below; the numbered sections give the full picture of our controls and their current limits.

EU-hosted by default

Primary application infrastructure runs on AWS eu-central-1 (Frankfurt, Germany). Cloudflare provides edge / Tunnel / routing globally, and Google Workspace delivers transactional email. Full subprocessor list: https://planvault.ai/subprocessors.

Encryption everywhere

TLS 1.2+ in transit (terminated at our Cloudflare edge and at the application ingress). AES-256-GCM at rest for all tenant secrets, AI provider credentials, and session event payloads — each organization has its own Data Encryption Key (DEK). Typical hosted SaaS uses Google Tink envelope wrapping (org key material protected by an AWS KMS–backed Key Encryption Key; LocalStack-compatible endpoints for development). Legacy hosted organizations may still use direct AWS KMS Encrypt/Decrypt of raw DEK bytes (dek_wrap = AWS_KMS). Self-hosted deployments usually supply a local Tink KEK via TINK_LOCAL_KEYSET_JSON from a secrets manager — AWS KMS is optional for that topology, not a universal requirement.

Per-tenant isolation

Every organization has a dedicated DEK. Deletion finalizes via crypto-shred (key destruction), so residual content in short-rotation backups becomes unrecoverable without touching shared storage. See Section 6 and Section 11.

BYOK for AI — your provider keys, stored encrypted and scoped to your org

You configure your own OpenAI / Anthropic / Google Cloud AI credentials in your PlanVault organization. They are stored encrypted under your organization's DEK (AES-256-GCM), decrypted only in application memory at the moment we call the provider on your behalf, and never shared across tenants. We do not operate a shared fallback account, we do not use your credentials for anything other than routing traffic that originated in your organization, and we do not use your runtime content to train any model. AI providers are therefore not our subprocessors — your contract with them governs that leg of processing. See Section 8.

Scoped, hash-stored project API keys

Project API keys are stored as SHA-256 hashes; the plaintext is shown once at creation and cannot be recovered. Each key has a scope list (HRN-style with wildcards) that the Runtime API enforces before any business logic runs. Rotation and revocation are immediate. See Section 5.

GDPR Article 32 controls, not yet independently certified

Our TOMs are designed against GDPR Article 32 and summarized in Annex B of our DPA. We do not currently hold SOC 2, ISO/IEC 27001, or ISO/IEC 27701 certifications — see Section 15 for status and roadmap conditions.

Subject-rights self-service

Console users can export their own data (JSON) and request erasure from within the product. Business customers exporting or erasing end-user data by externalUserId have dedicated admin endpoints. See Section 14 of the Privacy Policy and Section 14 below.

Responsible disclosure

Send vulnerability reports to [email protected]. We aim to acknowledge within 5 business days and to keep you informed through triage and remediation. See Section 16.

1. Our approach

We are an EU-based operator running a hosted platform for business customers. Our security model is built around three non-negotiable properties: (a) customer data is cryptographically isolated per organization; (b) we minimize the secrets and personal data that reach us in the first place (BYOK for AI, no payment processing today, no behavioral advertising); (c) every security-relevant control we describe corresponds to code in our production repository and config in our deployed environment — we do not publish aspirational controls as current ones.

Where a control is not yet in place (for example a third-party certification, a formal penetration-test report, or a dedicated SIEM), we say so explicitly rather than rely on lawyerly ambiguity. See Sections 9, 10, and 15.

2. Hosting and data residency

Primary application infrastructure: Amazon Web Services in region eu-central-1 (Frankfurt, Germany). All tenant data, at every layer, stays in that region.

Compute. The API, the Keycloak identity service, the LiteLLM router, the nginx edge proxy, PostgreSQL, and Redis all run as Docker containers on an EC2 compute instance (On-Demand). Persistent state for PostgreSQL and Redis lives on a dedicated EBS gp3 volume; AWS Data Lifecycle Manager (DLM) takes a daily snapshot of that volume, so backups inherit AWS-managed encryption and regional boundaries.

Storage. PostgreSQL on the EBS-backed volume is our primary tenant data store (organizations, projects, memberships, encrypted secrets, encrypted AI credentials, policy-consent evidence, audit rows, metadata for sessions and runs). In the hosted EU deployment, DynamoDB (also in eu-central-1) holds the Pekko execution journal, Pekko snapshots, and the encrypted session-event store. Self-hosted installations may instead configure `session-store.mode=postgres` or `file` (PostgreSQL tables and/or on-disk layout plus JDBC/H2 journal — see internal architecture docs). Application-layer keys: typical SaaS uses Tink with an AWS KMS KEK for wrapping org key material; legacy tenants may keep direct KMS wrap of DEK bytes. Optional KMS endpoint overrides apply for LocalStack or non-AWS test stacks.

Redis — idempotency and rate limiting. Redis runs on the same compute instance (EBS-backed data volume) and serves two security-relevant roles: (a) request idempotency — Runtime endpoints that start LLM turns (`POST …/sessions/{id}/messages`, `POST …/actions`) accept an `Idempotency-Key` header; when Redis is enabled, the first successful JSON response is cached under that key (per session + route, with a TTL) and replayed on retries, so a duplicated network call, a client-side retry, or a reverse-proxy replay cannot trigger a second paid LLM turn or a second side-effecting tool execution; (b) edge and application rate limits — nginx `limit_req` per request URI backed by Redis sliding-window counters reduce garbage traffic and guard database / HTTP pool exhaustion. With Redis disabled or misconfigured, idempotency is explicitly not enforced — our production configuration therefore treats Redis as part of the security and cost-control baseline.

Edge and transport. Cloudflare provides DNS, edge TLS termination, and a Cloudflare Tunnel from our AWS VPC back to the origin; customer requests therefore traverse Cloudflare's global network before reaching the Frankfurt origin. Cloudflare does not store customer business data beyond transient transport telemetry.

Transactional email. Google Workspace / Gmail SMTP under the planvault.ai domain is used for password reset, invites, and lifecycle notifications.

No marketing-site data collection. The public site at planvault.ai does not show a cookie banner, does not run analytics, and does not serve advertising — because we do not collect any of that data. The page set is a plain React SPA that renders the policies and this security page itself; there is no third-party tag manager, no tracking pixels, and no A/B testing vendor on the marketing surface.

The authoritative, versioned subprocessor list — including entity legal names, service roles, and processing regions — lives at https://planvault.ai/subprocessors and is referenced by Annex III of the DPA.

3. Encryption in transit and at rest

In transit. All external HTTPS traffic is TLS 1.2+ with modern cipher suites, terminated at Cloudflare and re-terminated at our application ingress. The admin console, the Runtime API, inbound webhook triggers, and outbound lifecycle webhooks all run over HTTPS. Internal traffic between the API, the database, and AWS services stays within the VPC / AWS backbone.

At rest — tenant data. Sensitive tenant data is encrypted with AES-256-GCM using a per-organization Data Encryption Key (DEK). Each encryption operation uses a fresh 12-byte nonce and produces a 16-byte authentication tag; tampered ciphertext is rejected on decryption rather than silently returning corrupt data. The encrypted classes include: organization secrets, project secrets, session-scoped secrets, stored AI provider credentials, session event payloads (chat content and tool results; tool-start parameter telemetry is minimized to bounded keys/counts with secret/PII-like key names redacted), and encrypted PII columns on the membership table.

At rest — storage layer. In addition to application-level encryption, AWS provides its standard infrastructure-level encryption (EBS, RDS, S3, DynamoDB) so that even ciphertext records are stored on encrypted volumes.

Policy-consent evidence. When a console user accepts the Privacy Policy and Terms of Service, we record the accepted versions, the timestamp, the client IP (resolved from the CF-Connecting-IP header set by our Cloudflare Tunnel, with X-Forwarded-For as fallback), and a truncated User-Agent string. This Article 7(1) GDPR "demonstrable consent" evidence is visible in the user's own data export and is deleted on account erasure.

4. Key management

Envelope encryption. Application-level encryption uses the envelope pattern: each organization has its own Tink AES256_GCM keyset (DEK), wrapped by a Key Encryption Key (KEK) provided via Google Tink. In typical hosted SaaS the KEK is AWS KMS (customer-managed CMK; use `TINK_KMS_KEY_URI` and `SECURITY_KMS_ENDPOINT_OVERRIDE` for LocalStack). Legacy organizations may still use direct AWS KMS wrap of DEK bytes (dek_wrap = AWS_KMS) instead of the Tink keyset path. In self-hosted deployments the KEK is commonly a local Tink keyset injected via the `TINK_LOCAL_KEYSET_JSON` environment variable — the operator is responsible for protecting that value using a secrets manager or sealed env injection. The plaintext keyset material exists only in application memory; per-organization AEAD primitives are cached with a short TTL to minimize re-derivation overhead.

DEK caching. For performance, the plaintext DEK is held in a per-organization in-memory cache keyed by its wrapped ciphertext so that repeated KMS Decrypt calls are avoided; invalidation happens on DEK rotation.

DEK rotation. Each organization DEK has a version counter. An authorized organization administrator (OWNER or ADMIN role) can trigger rotation through the admin API; a background worker re-encrypts dependent rows in batches, after which the old DEK is retired. During a healthy in-progress rotation, new encrypted writes use the pending DEK version; if rotation metadata is inconsistent and the pending key is unavailable, those writes fail closed with HTTP 409 rather than falling back to stale key material.

HMAC key. A dedicated 32-byte HMAC signing key is required and used for deterministic pseudonymization of external user identifiers (see Section 14); it is never the same value as the KMS CMK material.

5. Authentication and access control

Admin console (humans). Interactive admins authenticate through Keycloak using OpenID Connect. Our API verifies JWT signatures against the Keycloak JWKS endpoint with a short (5-minute) cache and automatic refresh on unknown key IDs; signature, expiration (exp), and not-before (nbf) claims are checked on every request. MFA, password policies, and session lifetime are enforced at the Keycloak realm and are configurable by the operator.

Runtime API (services). Machine clients authenticate with Project API Keys issued per project. The plaintext key is shown exactly once at creation (with a short four-character preview retained for console display) and is stored only as a Base64-encoded SHA-256 hash. Authentication therefore cannot be recovered from a database backup alone.

Scoped authorization. Every Project API Key row stores an explicit scope list in HRN format (for example hrn:project:session:create, hrn:project:session:*, hrn:project:*). Each secured Runtime route declares the scope it requires; the server allows the call only if a stored scope on the matching key covers that requirement via left-to-right segment comparison with * wildcard support. A key that belongs to a different project is rejected (403) before the business logic runs.

Session-level provenance. Runtime session rows record their creator (API key id or console user id). A project API key may use only sessions it created. JWT callers with organisation role MEMBER may use only sessions they started themselves. JWT callers with OWNER, ADMIN, or DEVELOPER may access any session in the project via Runtime routes (including legacy rows where provenance metadata is absent). Owner/Admin-only Admin API operations (for example deleting all sessions in a project, audit exports, or certain DSAR tooling) remain separately gated. Sensitive administrative actions are recorded in the organisation audit log where the product emits them.

Key lifecycle. Admin endpoints expose create, rotate, patch (name / scopes), and delete for non-primary keys; rotation of any key returns the new plaintext exactly once. Revocation (deletion) is immediate — revoked keys no longer authenticate, even for sessions they previously started.

Org RBAC. Organization membership has four roles: OWNER (full control; last-owner protection prevents lock-out), ADMIN (manage resources, members, secrets, models; cannot delete the organisation), DEVELOPER (engineering and catalog surfaces — tools, LLM, integrations, scenarios, spend reads, org secrets — aligned with the product; cannot manage org membership, primary API-key lifecycle, audit-log listing, or other Owner/Admin-only controls), MEMBER (read-only org resources in the console; Runtime JWT HRN scopes are a subset). Role transitions that would remove or demote the last OWNER are rejected.

Automation and integrations. Every `/admin/v1/*` call in the hosted product uses the same contract as the interactive console: a verified Keycloak access JWT in `Authorization: Bearer`. For CI or scripts, obtain a token from your realm (for example the OAuth2 token endpoint) under your organization's security policy. There is no separate static “admin secret” that replaces a JWT for these public Admin routes. Cross-tenant platform operations use internal operator controls rather than the shared product Admin API.

Client-side secret storage (the browser). PlanVault does not write any authentication secret or API-key plaintext to browser persistent storage. Keycloak access and refresh JWTs used by the admin console are held in `keycloak-js` in-memory state with silent refresh; Keycloak session cookies (`AUTH_SESSION_ID`, `KC_RESTART`, `KEYCLOAK_IDENTITY`, `KEYCLOAK_SESSION`) are HttpOnly with SameSite attributes set by the Keycloak server. When a user elects to use the built-in Runtime console, the product may persist the project API key in that user's own server-side UI preferences (access-gated by the same JWT); the value stays in React in-memory state and is never written to `document.cookie`, `localStorage`, or `sessionStorage`. Legacy pre-2026-Q2 local-storage keys (`planvault_auth_token`, `planvault_admin_token`) are force-cleared on every page load during AppState bootstrap to protect users of older builds. The full inventory of entries that **are** present in browser storage — all of which are non-secret UI preferences or Keycloak-managed session cookies — is published in our Cookie Policy (https://planvault.ai/cookies). This design removes the "passive XSS exfiltration of secrets from localStorage" class of findings common in external audits; XSS mitigation at the execution layer (Content-Security-Policy, output sanitization, strict React rendering) is documented in Section 9.

6. Tenant isolation

Logical isolation. All tenant-scoped tables carry an organization identifier, and every admin query is scoped by the authenticated caller's organization membership before execution. Cross-organization reads are rejected at the API boundary; the database layer uses parameterized queries throughout so user-supplied identifiers cannot alter query shape.

Cryptographic isolation. Because each organization has its own DEK, ciphertext written for one tenant is unreadable by any code path that has not explicitly loaded that tenant's DEK. In AWS KMS mode, the KMS Decrypt call is further gated by the IAM policy attached to the application role.

Project-level isolation inside an organization. A Runtime request authenticated by a Project API Key carries its project id in the URL path; the server refuses to serve data outside the project that issued the key, even when the caller is a member of the owning organization.

7. Secrets management

Layered vault. Secrets are stored at three scopes — organization, project, and session — each encrypted with the organization DEK. At execution time they are merged in that order (session overrides project, project overrides organization) and combined with synthetic entries derived from verified AI provider credentials.

Never sent to the LLM. Secret values are never placed into the prompt sent to the language model. The planner receives only each secret's name, type, and description; the model is instructed to reference configured secrets by variable name in tool arguments (for example apiKey=OPENAI_API_KEY). At execution, the FSM resolves names to plaintext and injects them into tool HTTP headers, query strings, or bodies.

Never logged, never exported. Decrypted secret material does not appear in session events (which are themselves stored encrypted), application logs (values are masked), API responses, or the GDPR data export.

Session-scoped lifecycle. Ephemeral per-session secrets are stored in a dedicated table whose foreign key to the session row carries ON DELETE CASCADE: when a session is deleted (by retention job, DSAR erasure, or explicit admin action), its session-scoped secrets are removed in the same transaction, so there is no window in which orphaned ciphertext can persist after the owning session is gone.

8. Bring Your Own Key (BYOK) for AI providers

You supply the credentials. Customers who want to use AI features configure their own OpenAI, Anthropic, or Google Cloud AI credentials in their PlanVault organization. Without a verified provider credential in your own organization, chat is blocked — we do not silently route your traffic through any shared or platform-operator provider account.

Storage of your provider credentials. Each provider credential you add is encrypted at the application layer with your organization's DEK (AES-256-GCM, 12-byte nonce + 16-byte authentication tag) and stored in `organization_llm_providers`. The plaintext credential exists in application memory only for the duration of a single LLM call and only in the request that originated in your organization; it is never written to logs, never included in session events, never returned by the admin API after creation (the UI returns only the last four characters for operator recognition), and never exported by the GDPR export endpoint.

Scoped to your org, never shared. Your provider credentials are scoped to the organization that added them. We do not have a code path that reads provider credentials belonging to one organization while serving a request from another organization, and every call from the planner / executor to a provider happens inside an organization-scoped context that carries exactly that organization's DEK. We do not maintain a shared OpenAI / Anthropic / Google account for customer traffic; if your credentials are revoked or exhausted your AI features stop working, and PlanVault does not silently fall back to any other account.

What the LLM actually sees. When we call the provider, we send the prompt, the tool-specification metadata (names, types, descriptions — not secret values; see Section 7), and the contents of the conversation that the planner needs to resolve the current turn. We do not attach other organizations' data, and we do not attach platform-operator credentials or platform-internal identifiers that would be meaningful to the provider.

PlanVault is not a subprocessor for that leg. Because AI providers are called using your credentials on your behalf, the provider's terms, data-processing terms, and privacy policy apply directly to that processing — your legal relationship is with them, not with us, for that leg of the data flow. AI providers are therefore listed in our subprocessors page for transparency but are not Annex III subprocessors of our DPA.

No training on your content. Customer runtime content (prompts, tool calls, session events) is not used to train any model that PlanVault operates. Whether any on-provider training occurs (for example OpenAI's enterprise vs. consumer API defaults) is governed by your agreement with that provider; we recommend you select the no-training / enterprise tier at the provider and we will honor whatever configuration your provider account enforces.

Semantic Routing Cache (tenant embeddings). Separately from LLM providers, when the organization has not disabled Semantic Routing Cache, PlanVault derives anonymized vector embeddings from workflow queries and stores them only in your tenant's PostgreSQL data under your organization DEK — they are not sent to AI providers as part of PlanVault→provider traffic and are not used to train any foundation model. They exist solely to optimize routing and latency inside your tenant; the organization owner can disable the feature at any time, which triggers immediate deletion of stored vectors. Details and legal bases are in the Privacy Policy (Sections 5 and 14).

Rotation and revocation on your side. You can rotate or revoke your provider credentials inside your provider's console at any time; we do not need to be notified. The next call after the provider rejects the old credential simply fails, and you can upload the new one in the PlanVault admin console.

9. Application security and secure development

Supply chain. The backend is a JVM service (Scala, Apache Pekko) and the frontend is a Vite + React + TypeScript app. Dependencies are pinned at build time; dependency vulnerability scanning and an SBOM pipeline are part of our release workflow.

Parameterized data access. All database access uses typed, parameterized queries; string concatenation is not used to build SQL. ORM-style joins and paginated lists are bounded by explicit per-route limits.

Safe error responses. API error responses follow RFC 7807 (application/problem+json). An allow-list of safe internal messages is mapped to stable client strings; everything else is collapsed to a generic "internal error" message with a correlation id, while full stack traces stay in server logs. Public webhook endpoints in particular use a single uniform 404 so unauthenticated callers cannot infer whether a trigger exists, is disabled, or failed HMAC verification.

Webhook integrity. Inbound public webhook triggers require HMAC-SHA256 by default (the "none" auth method is rejected); signatures are computed over the raw JSON body and compared before any session is created. Outbound lifecycle webhooks are signed with HMAC over the raw body (X-Signature header) and must be delivered over HTTPS.

Rate limiting. Edge limits (nginx) bound per-URI request rates; optional Redis sliding-window limits back replay protection (Idempotency-Key) and guard pool exhaustion. With Redis disabled, idempotency is not enforced — see the production runbook for the required config.

Code review. Every change is reviewed before it reaches main; CI runs unit, integration, and end-to-end tests (Scala + TypeScript) before merge and before production release.

Penetration testing. We do not currently publish results of a third-party penetration test. Planned once we have enterprise customers or accelerator funding to commission one; see Section 15.

10. Logging, monitoring, and audit

Application logs. The API emits structured JSON logs including a request identifier, optional correlation / trace identifiers (X-Request-Id, X-Correlation-ID, W3C traceparent), and role-relevant metadata. Secret values, request bodies that could contain secrets, and decrypted session payloads are not logged.

Retention. Application / ingress / request logs are rotated per container and host log-driver policies and are not retained in a dedicated SIEM; a typical window is up to twelve months. Operator retention choices for each deployment are reflected in the internal data-retention register and available to business customers on request.

Admin audit. Organization and project audit endpoints expose security-relevant operations for administrator review: member role changes, API-key issuance / rotation / revocation, DEK rotation, provider-credential changes, secret create / update / delete, retention-cutoff changes, organization or project deletion, DSAR export / erase actions, scenario and tool-catalog edits, and any other change with a tenant-wide or project-wide security or billing impact.

Health and uptime. Service health is monitored through AWS and infrastructure dashboards; sustained degradation or incidents are communicated through the support channel and, where applicable, through the incident-response process in Section 13.

11. Data retention and deletion

Per-organization session retention. Each organization has a session-retention cutoff in days (bounded between 1 and 1461). A daily job deletes sessions older than that cutoff together with their encrypted event payloads. Administrators can reduce the cutoff at any time in settings.

Organization deletion and crypto-shred. When an authorized administrator deletes an organization, the tenant enters a 7-day grace window during which it is invisible to all users but can be restored on written customer request. At the end of the window, deletion is finalized by crypto-shred: the organization-specific DEK is permanently destroyed and tenant records are purged. Any residual content in short-rotation backups becomes unrecoverable because the key needed to decrypt it no longer exists.

Pekko journal cleanup and tool-parameter minimization. During execution, the ephemeral FSM journal stores tool-start telemetry as a bounded audit shape (parameter keys/counts only; secret/PII-like key names redacted). Raw tool parameter values are not written to new tool-start journal events or SSE/history payloads. After FSM execution reaches a terminal outcome, intermediate persistence entries in the ephemeral execution journal are deleted by a background reconciler. The reconciler first verifies that the authoritative encrypted session event mirror exists, so transient execution state is removed from the ephemeral execution layer without racing the long-term history store.

Data-subject erasure. Individual GDPR erasure requests are processed immediately through the admin export / erase endpoints and through the console-user self-service erase endpoint — the 7-day grace window above applies only to whole-organization deletion.

12. Backups and disaster recovery

We rely on short-rotation managed backups of the PostgreSQL and DynamoDB data stores provided by the underlying AWS services. These backups are encrypted with AWS-managed keys and are kept only for the rotation window configured in the environment.

Crypto-shred interacts with backups. Because tenant data is encrypted at the application layer with a per-organization DEK, destroying that DEK makes residual ciphertext in backups unrecoverable without further bulk deletion of backup artifacts. Section 11 describes the lifecycle.

Documented restore path. Disaster-recovery steps for database, DynamoDB, and application state are maintained in our internal production runbook; a current-RPO / RTO summary is available to enterprise customers under NDA.

13. Incident response and breach notification

Detection. Suspected incidents (unauthorized access, data exposure, integrity compromise) are raised through our support / privacy inboxes, through Cloudflare and AWS alerts, or through application error rates and audit anomalies.

Containment and triage. On a confirmed incident we (a) contain the scope (revoking keys, rotating DEKs, disabling affected accounts), (b) preserve forensic evidence (logs, audit rows, affected ciphertext metadata), (c) determine whether personal data was affected, and (d) identify the controllers that need to be notified.

Notification timing. Where we act as processor and a personal-data breach affects Customer data, we notify the affected controller customer(s) without undue delay after becoming aware — our operational target is within 72 hours — with the information available at that time, followed by supplementary updates as the investigation progresses. Our contractual notification obligations and contents follow Article 33 GDPR and are detailed in our DPA.

Where we act as controller (for example for our own website visitors or account holders), we notify the competent supervisory authority under Article 33 GDPR and affected data subjects under Article 34 where required.

14. GDPR and subject rights

Console user self-service. Signed-in console users can export their own data through GET /admin/v1/me/data-export (a portable JSON package including policy-consent history) and request erasure through POST /admin/v1/me/data-erasure. These routes require the caller’s Keycloak-issued access token for the interactive user; they are not satisfied by credentials that do not represent that end user.

Tenant admin export and erase. For a business customer acting as controller, administrators can export all organization data and can export or erase data for a specific end user identified by externalUserId. The erase endpoint removes all sessions for that user within the organization, cascading encrypted events and session-scoped secrets.

Pseudonymization of external user ids. External user identifiers provided by your integration are hashed with HMAC-SHA256 before storage so that the original identifier cannot be recovered from the database alone. The same identifier always maps to the same hash within a given deployment, so correlation and DSAR fulfilment remain possible.

Policy-consent audit. Each acceptance of the Privacy Policy or Terms of Service produces an append-only row with the accepted version, timestamp, client IP, and User-Agent — satisfying GDPR Article 7(1) demonstrable-consent evidence.

For the broader legal framework (legal bases, international transfers, rights of EEA / UK / Switzerland residents), see our Privacy Policy at https://planvault.ai/privacy.

15. Certifications and assurance

What we hold today. PlanVault is operated by a single Polish JDG; we do not currently hold SOC 2 Type I or Type II attestations, ISO/IEC 27001 certification, ISO/IEC 27701 certification, HIPAA / HITRUST / PCI-DSS attestations, or an active third-party penetration-test report.

What we rely on instead. We rely on (a) the documented technical and organizational measures described on this page and in Annex B of our DPA, aligned with GDPR Article 32; (b) AWS's own compliance posture for the underlying infrastructure layer (AWS holds SOC 2 and ISO 27001 for eu-central-1 among other attestations) — note that AWS's compliance is for the infrastructure layer only and does not substitute for our own; (c) Cloudflare's certifications for the edge layer; (d) standard contractual clauses and subprocessor flow-down in our DPA.

Roadmap conditions. A SOC 2 Type I engagement, a third-party penetration test, and a formal ISMS documentation pack are scoped for the year following our first enterprise customer win or admission to a pre-seed accelerator program (whichever comes first), because either trigger provides the budget and minimum team size that make those activities meaningful rather than ceremonial. We will update this page when either is in progress.

Customer-specific diligence. We respond in good faith to vendor security questionnaires (CAIQ, SIG-lite, and custom) for prospective customers under NDA; see Section 18.

16. Responsible disclosure and reporting a vulnerability

Where to send. Email [email protected] (dedicated inbox for vulnerability reports and security reviews) or [email protected] (if the report has a privacy / data-subject dimension) with a description of the issue, reproduction steps or a minimal proof of concept, and any affected account identifiers. If you need to send sensitive evidence, say so in your first message and we will arrange an encrypted channel.

What we ask. Please give us a reasonable remediation window before public disclosure (we aim to triage within 5 business days and to fix or mitigate high-severity issues within 30 days). Do not access other customers' data, do not degrade service for others, and do not perform denial-of-service testing against production. Limit automated scanning to accounts you own.

What you can expect. Acknowledgement within 5 business days, a triage decision (accepted / needs-more-info / not-applicable) within 10 business days, regular status updates until the report is resolved, and public credit in our release notes if you would like it. We do not currently run a paid bug-bounty program.

Out-of-scope. Reports based solely on automated scanner output without a demonstrated impact, best-practice recommendations (for example missing security headers on the marketing site) without a concrete exploit, social engineering of our staff, and denial-of-service against the shared infrastructure.

17. Shared responsibility

What PlanVault is responsible for. Secure operation of the platform code and infrastructure as described above: authentication verification, encryption and key management, tenant isolation, logging controls, secure-by-default configuration of the hosted deployment, and subject-rights fulfilment routes.

What the Customer is responsible for. Choosing strong passwords or SSO at your identity provider, managing OWNER / ADMIN / DEVELOPER / MEMBER role assignments, rotating project API keys you distribute, keeping your own copies of plaintext keys off the PlanVault platform, configuring your own AI provider accounts and their data-processing terms (BYOK), curating what you submit into prompts and tool payloads (especially special-category data), and notifying us without undue delay if you suspect credential compromise or other misuse on your side.

18. Contact and requesting documentation

Security questions, vendor questionnaires, and vulnerability reports: [email protected] (see Section 16). Privacy, data-subject rights, and breach notifications: [email protected]. General support: [email protected]. In practice all three addresses reach the same operator.

Upon request under a mutual NDA we share: our latest internal processing-activities register summary, our data-retention register, our vendor / subprocessor legal-evidence index, the current production runbook excerpt for backup and disaster recovery, and a fresh DPA copy with any redlines your team proposes.

Postal: Bohdan Matviichuk, ul. Dziewanny 21/19, 20-539 Lublin, Poland. VAT / NIP: PL7123452217.

If you have questions about this Security page or about how we protect your data, email [email protected].