Capability group 01
Accounts, roles & project access
Give each person the smallest useful operating surface: first by role, then by assigned project.
Session and API authentication
Use a browser session or its paired bearer-token form for API calls without creating separate login identities.
Hardened password handling
bcrypt protects passwords, and supported legacy hashes upgrade after a successful login.
Login throttling
Repeated failures are limited per normalized username and source IP after 10 attempts in 15 minutes; success clears the counter.
Uniform login responses
Known and unknown accounts receive the same error and comparable bcrypt work, reducing enumeration and timing signals.
Optional login verification
Email a single-use six-digit code with expiry, attempt limits, resend limits, and cooldown after password login.
Separate password recovery
An eight-character email code lasts 15 minutes, allows five attempts, and changes nothing until verified.
Recovery abuse controls
Forgot requests return the same generic response and are rate-limited for known and unknown addresses.
Complete revocation
A password reset revokes every user session and token; logout revokes both forms of the same login session.
Secure cookie defaults
HTTP-only, SameSite Strict cookies become Secure under direct TLS or a deliberately trusted HTTPS proxy.
Built-in and custom roles
Start with Administrator, Developer, and Viewer, or define valid role policy through the environment.
Two permission layers
A global role opens product areas while per-project read, write, or none access controls files, Git, and Docker inside a repository.
Account and project administration
Administrators can enable, disable, create, edit, and delete users and projects without removing the final enabled administrator.
Scoped RDS IP allowlisting
Explicitly authorized users can add their validated public IP after password reauthentication, strict request validation, and rate limiting.
Idempotent security-group updates
An already-present AWS ingress rule counts as success instead of creating operator noise.