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:
- SSH into the server with your own credentials.
- Edit
~/.ssh/authorized_keysfor the login the platform uses, and remove the line beginning withssh-ed25519 AAAA...that matches the fingerprint shown on the server's detail page in your dashboard. - 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
currentsymlink 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.