This page describes what Code</>sensei can see, what it stores, how it stores it, and how you cut access if you ever need to. None of the technical claims here require trust — they are verifiable against the running platform.

What the platform stores

Code</>sensei records the following per server you add:

  • The hostname or IP, port, and login username you supplied — these are stored in plain text because they are required for every deploy attempt and are not sensitive on their own.
  • If you use key-based auth (the default), an ephemeral Ed25519 private key the platform generated. The corresponding public key was shown to you once and pasted into your server. The private key is stored Fernet-encrypted on the platform's database column.
  • If you use the legacy password-based flow, the password is stored Fernet-encrypted on the same column convention.

Code</>sensei does not store the contents of your repository. The platform's worker clones into a release directory on your server during a deploy and never copies that working tree back. Logs from the deploy run (which may include filenames, dependency names, and error messages) are persisted on the platform's database; do not echo secrets in shell commands that run during your deploy if you intend to keep them out of platform-side storage.

Field-level encryption

The encrypted columns use Python's cryptography.fernet.Fernet. Fernet is AES-128-CBC under HMAC-SHA-256, with the IV and HMAC bundled into the ciphertext. The ciphertext you would see if you opened the database row directly looks like gAAAAABhJ8... — base64url with a Fernet version byte.

The encryption key lives in the platform's runtime environment as the CODESENSEI_FIELD_KEY variable. It is not stored in the database, the Git repository, or any image artifact. Rotating the key requires decrypting every encrypted field with the old key and re-encrypting with the new one — see the runbook in docs/notes.md for the operator-side procedure.

Revoking access

If you ever need to cut Code</>sensei off from a server immediately:

  1. SSH into the server with your own credentials.
  2. Edit ~/.ssh/authorized_keys for the login the platform uses, and remove the line beginning with ssh-ed25519 AAAA... that matches the fingerprint shown on the server's detail page in your dashboard.
  3. Subsequent deploy attempts from the platform will fail at the SSH handshake. The platform will mark the next deploy failed; your application keeps running because the current symlink still points at the last successful release.

Deleting the server from the dashboard is a soft revoke: it removes the platform's stored credentials and tears down any per-deploy DNS records the platform created, but it does not touch the authorized_keys file on your server. The two-step sequence — remove the key on your server, then delete the platform row — is the safest order.

Blast radius

If a Code</>sensei worker were compromised, an attacker would inherit SSH access to every server every customer of the platform has added, subject to the encrypted-key model. They would not have access to repository contents (we hold no copies) nor application data (we never connect to your database). They would have full root on those servers via the configured login, which is why the platform documents running deploys as a non-root account with sudo for the narrow set of operations the deploy script needs — a hardening recipe is in the server preparation guide.

Reporting issues

Security reports go to security@codesensei.cloud. We acknowledge within one business day. Please do not include proof-of-concept payloads that affect other tenants without coordinating first.

Audit log

Every state-changing action on a server, project, or deployment row is recorded on a per-account audit table. The dashboard exposes the log under Settings → Audit log filtered to the current user. The records carry the actor user ID, the action name (server.created, deployment.queued, project.env_updated, …), the target object's UUID, the client IP address the action originated from, and a UTC timestamp. Failed authentication attempts are recorded with their hashed input, never the cleartext, so a compromised audit table does not hand an attacker working credentials. The audit log is read-only from the dashboard; you cannot edit or delete rows.

Session and credential management

The web UI authenticates via the standard Django session cookie: HttpOnly, Secure, SameSite=Lax. Session lifetime defaults to fourteen days of inactivity; an explicit sign-out invalidates the cookie immediately and forces re-authentication on the next request. Password storage uses Django's default PBKDF2-SHA256 hasher with the framework's current iteration count — passwords are never reversible from the database. There is no plaintext password reset path; the reset flow emails a single-use token to the address on file and that token expires after fifteen minutes.

If you suspect your account has been accessed without your authorization, the dashboard's Settings → Sessions page lists every active session by client IP, user agent string, and last seen timestamp. Click Sign out on any row to invalidate that session immediately; click Sign out everywhere to invalidate all sessions including the one you are currently using.

Data residency

The platform's own database — the one that holds accounts, server metadata, encrypted credentials, and the audit log — runs in a single region today. The country we currently operate from is documented on the privacy page. The deploy targets are your servers; the data that lives on them stays in whatever region you picked when you provisioned the server. If you have data-residency constraints that the current single-region platform database conflicts with, contact us via reach-us@codesensei.cloud before signing up.

Dependencies and supply-chain

The platform itself runs on a pinned set of Python dependencies audited monthly against the published CVE feeds for the project's ecosystem. Each release ships with the dependency manifest baked into the deploy artifact — the same pinning applies at every replica. We publish the SHA-256 of the deployed release image at https://codesensei.cloud/healthz/; pin a hash if you want to detect a release rollout.