docs: consolidate repository guides and preserve audit history
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
# Security
|
||||
|
||||
Security is enforced in the API and deployment topology, not by UI visibility. The current baseline includes tenant owner filters, local/Google/Microsoft identity options, cookie CSRF protection, rate limits, TOTP, session revocation, validated uploads/imports, bounded document parsing, private AI networking, and structured error handling.
|
||||
|
||||
- [Authentication](authentication.md)
|
||||
- [Authorization and tenancy](authorization.md)
|
||||
- [Sessions and rate limits](sessions.md)
|
||||
- [File and import security](file-security.md)
|
||||
- [Current findings and verification limits](security-notes.md)
|
||||
|
||||
Historical audits remain recoverable in [`../_archive/`](../_archive/); only verified current claims belong here.
|
||||
@@ -1,35 +0,0 @@
|
||||
# AI Security
|
||||
|
||||
## Purpose
|
||||
|
||||
Protect against AI-related risks.
|
||||
|
||||
---
|
||||
|
||||
# Prompt Injection
|
||||
|
||||
Untrusted content:
|
||||
|
||||
- Job descriptions.
|
||||
- Uploaded CVs.
|
||||
- Emails.
|
||||
|
||||
must not control AI behaviour.
|
||||
|
||||
---
|
||||
|
||||
# AI Output Validation
|
||||
|
||||
Check:
|
||||
|
||||
- Unsupported claims.
|
||||
- Dangerous content.
|
||||
- Formatting issues.
|
||||
|
||||
---
|
||||
|
||||
# Data Handling
|
||||
|
||||
Only send required information.
|
||||
|
||||
Avoid unnecessary exposure.
|
||||
@@ -1,40 +0,0 @@
|
||||
# API Security
|
||||
|
||||
## Requirements
|
||||
|
||||
All APIs must:
|
||||
|
||||
- Authenticate correctly.
|
||||
- Validate input.
|
||||
- Return safe errors.
|
||||
|
||||
---
|
||||
|
||||
# Rate Limiting
|
||||
|
||||
Protect:
|
||||
|
||||
- Login.
|
||||
- AI endpoints.
|
||||
- File uploads.
|
||||
- Public CV pages.
|
||||
|
||||
---
|
||||
|
||||
# API Keys
|
||||
|
||||
Admin-only.
|
||||
|
||||
Never expose:
|
||||
|
||||
- Provider keys.
|
||||
- Secrets.
|
||||
- Tokens.
|
||||
|
||||
---
|
||||
|
||||
# External APIs
|
||||
|
||||
Validate responses.
|
||||
|
||||
Do not trust third-party data.
|
||||
@@ -1,84 +1,5 @@
|
||||
# Authentication
|
||||
|
||||
## Purpose
|
||||
Local email/password accounts issue signed local JWTs and can use an HttpOnly `jobtracker_auth` session cookie. Google and Microsoft identity sign-in are optional and configured separately from Gmail/Graph mail access. Registration is disabled by default; email verification, Turnstile, and production auth requirements are configuration gates.
|
||||
|
||||
Define user login and registration.
|
||||
|
||||
---
|
||||
|
||||
# Supported Methods
|
||||
|
||||
Users should be able to:
|
||||
|
||||
## Email Registration
|
||||
|
||||
Create account using:
|
||||
|
||||
- Email.
|
||||
- Password.
|
||||
- Confirmation.
|
||||
|
||||
---
|
||||
|
||||
## OAuth Registration/Login
|
||||
|
||||
Support:
|
||||
|
||||
- Google.
|
||||
- Microsoft.
|
||||
|
||||
---
|
||||
|
||||
# Expected Behaviour
|
||||
|
||||
If OAuth user does not exist:
|
||||
|
||||
Create account automatically.
|
||||
|
||||
Example:
|
||||
|
||||
User clicks:
|
||||
|
||||
"Continue with Google"
|
||||
|
||||
↓
|
||||
|
||||
Authenticate
|
||||
|
||||
↓
|
||||
|
||||
No account exists
|
||||
|
||||
↓
|
||||
|
||||
Create account
|
||||
|
||||
↓
|
||||
|
||||
Login
|
||||
|
||||
---
|
||||
|
||||
# Password Requirements
|
||||
|
||||
Support:
|
||||
|
||||
- Secure hashing.
|
||||
- Password reset.
|
||||
- Password change.
|
||||
|
||||
---
|
||||
|
||||
# Authentication UX
|
||||
|
||||
Users should have:
|
||||
|
||||
- Clear errors.
|
||||
- Loading states.
|
||||
- Recovery options.
|
||||
|
||||
Avoid:
|
||||
|
||||
"Authentication failed"
|
||||
|
||||
without explanation.
|
||||
Password reset and verification use SMTP. TOTP two-factor authentication includes encrypted secrets, recovery codes, trusted devices, and pending-token flow. JWT issuer, audience, key, lifetime, and external client IDs are documented in [environment variables](../configuration/environment-variables.md).
|
||||
|
||||
@@ -1,43 +1,5 @@
|
||||
# Authorization
|
||||
# Authorization and tenancy
|
||||
|
||||
## Purpose
|
||||
Tenant-owned records carry `OwnerUserId` directly or through a parent. `JobTrackerContext` applies global owner filters with deny-on-null semantics; services and background work use explicit owner checks when they bypass request-scoped filters. Admin users access user management, audit, and system readiness surfaces through Identity roles.
|
||||
|
||||
Control access to resources.
|
||||
|
||||
---
|
||||
|
||||
# User Isolation
|
||||
|
||||
A user must only access:
|
||||
|
||||
- Their jobs.
|
||||
- Their CV.
|
||||
- Their files.
|
||||
- Their emails.
|
||||
- Their settings.
|
||||
|
||||
---
|
||||
|
||||
# Admin Role
|
||||
|
||||
Admins may access:
|
||||
|
||||
- System settings.
|
||||
- Provider configuration.
|
||||
- Monitoring.
|
||||
|
||||
---
|
||||
|
||||
# API Rules
|
||||
|
||||
Every protected endpoint must verify:
|
||||
|
||||
1. User identity.
|
||||
2. User permission.
|
||||
3. Resource ownership.
|
||||
|
||||
---
|
||||
|
||||
# Never Trust Frontend
|
||||
|
||||
The backend must enforce permissions.
|
||||
A browser route or hidden control is not an authorization boundary. Add server-side authorization and an ownership regression test for every new resource or endpoint.
|
||||
|
||||
@@ -1,56 +1,5 @@
|
||||
# File Security
|
||||
# File and import security
|
||||
|
||||
## Purpose
|
||||
Attachment uploads use a managed data root, validated metadata, size/type/signature checks, and safe download paths. Parser decoding is isolated and resource-bounded. URL import validates destinations and rejects unsafe redirects; DNS rebinding and actual socket binding remain a documented verification concern.
|
||||
|
||||
Protect uploaded documents.
|
||||
|
||||
---
|
||||
|
||||
# File Types
|
||||
|
||||
Potential uploads:
|
||||
|
||||
- PDF.
|
||||
- DOCX.
|
||||
- Images.
|
||||
- Portfolio files.
|
||||
|
||||
---
|
||||
|
||||
# Validation
|
||||
|
||||
Check:
|
||||
|
||||
- File type.
|
||||
- File size.
|
||||
- File contents.
|
||||
|
||||
Never trust extensions.
|
||||
|
||||
---
|
||||
|
||||
# Processing
|
||||
|
||||
Uploaded files may contain:
|
||||
|
||||
- Malicious content.
|
||||
- Embedded scripts.
|
||||
- AI prompt injection.
|
||||
|
||||
Treat as untrusted.
|
||||
|
||||
---
|
||||
|
||||
# Storage
|
||||
|
||||
Requirements:
|
||||
|
||||
- Secure naming.
|
||||
- Access control.
|
||||
- User ownership checks.
|
||||
|
||||
---
|
||||
|
||||
# PDF Processing
|
||||
|
||||
Never directly trust extracted text.
|
||||
Generated CV previews are sandboxed and public CV/PDF links are random, revocable, noindex, and rate-limited. Never log or document private file contents, connection strings, or bearer tokens.
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# Input Validation
|
||||
|
||||
## Purpose
|
||||
|
||||
Protect the application.
|
||||
|
||||
---
|
||||
|
||||
# Validate
|
||||
|
||||
All inputs:
|
||||
|
||||
- Forms.
|
||||
- APIs.
|
||||
- Imports.
|
||||
- Files.
|
||||
- AI outputs.
|
||||
|
||||
---
|
||||
|
||||
# Protection Against
|
||||
|
||||
Examples:
|
||||
|
||||
- SQL injection.
|
||||
- XSS.
|
||||
- HTML injection.
|
||||
- Malicious uploads.
|
||||
|
||||
---
|
||||
|
||||
# CV Builder
|
||||
|
||||
Special attention:
|
||||
|
||||
Users can create:
|
||||
|
||||
- Custom sections.
|
||||
- HTML-like content.
|
||||
- Formatting.
|
||||
|
||||
The renderer must sanitise content.
|
||||
|
||||
---
|
||||
|
||||
# Rule
|
||||
|
||||
Never render user content directly without validation.
|
||||
@@ -1,64 +0,0 @@
|
||||
# Security Overview
|
||||
|
||||
## Purpose
|
||||
|
||||
Define security requirements for Jobjakt.
|
||||
|
||||
The application stores sensitive career information including:
|
||||
|
||||
- CVs.
|
||||
- Employment history.
|
||||
- Personal details.
|
||||
- Job applications.
|
||||
- Documents.
|
||||
- Communication.
|
||||
|
||||
Security must be considered a core product requirement.
|
||||
|
||||
---
|
||||
|
||||
# Security Goals
|
||||
|
||||
Jobjakt should provide:
|
||||
|
||||
- Secure authentication.
|
||||
- Strong user separation.
|
||||
- Safe document handling.
|
||||
- Protected APIs.
|
||||
- Secure AI integrations.
|
||||
|
||||
---
|
||||
|
||||
# Security Principles
|
||||
|
||||
## Least Privilege
|
||||
|
||||
Users should only access their own data.
|
||||
|
||||
Admins have additional permissions.
|
||||
|
||||
---
|
||||
|
||||
## Secure By Default
|
||||
|
||||
Features should default to safe behaviour.
|
||||
|
||||
---
|
||||
|
||||
## Validate Everything
|
||||
|
||||
All external input should be considered untrusted.
|
||||
|
||||
Sources:
|
||||
|
||||
- Forms.
|
||||
- APIs.
|
||||
- Uploaded files.
|
||||
- AI responses.
|
||||
- Imported job descriptions.
|
||||
|
||||
---
|
||||
|
||||
## Do Not Over-Engineer
|
||||
|
||||
Security should protect users without harming usability.
|
||||
@@ -1,51 +0,0 @@
|
||||
# Privacy
|
||||
|
||||
## Principles
|
||||
|
||||
Users own their information.
|
||||
|
||||
---
|
||||
|
||||
# Requirements
|
||||
|
||||
Support:
|
||||
|
||||
- Data deletion.
|
||||
- Export.
|
||||
- Consent.
|
||||
|
||||
---
|
||||
|
||||
# Public CV
|
||||
|
||||
Users choose:
|
||||
|
||||
Enabled.
|
||||
|
||||
Disabled.
|
||||
|
||||
---
|
||||
|
||||
# Public URLs
|
||||
|
||||
Use:
|
||||
|
||||
Random UUID.
|
||||
|
||||
Example:
|
||||
|
||||
/cv/8a92f3e2-xxxx
|
||||
|
||||
Avoid:
|
||||
|
||||
Predictable usernames.
|
||||
|
||||
---
|
||||
|
||||
# Future SaaS
|
||||
|
||||
Consider:
|
||||
|
||||
- Privacy policy.
|
||||
- GDPR compliance.
|
||||
- Data processing agreements.
|
||||
@@ -1,51 +0,0 @@
|
||||
# SaaS Security
|
||||
|
||||
## Future Requirements
|
||||
|
||||
When moving to SaaS:
|
||||
|
||||
Support:
|
||||
|
||||
- Multiple users.
|
||||
- Subscription plans.
|
||||
- Usage limits.
|
||||
|
||||
---
|
||||
|
||||
# Tenant Isolation
|
||||
|
||||
Every resource belongs to:
|
||||
|
||||
User
|
||||
|
||||
or
|
||||
|
||||
Organisation.
|
||||
|
||||
---
|
||||
|
||||
# Billing Security
|
||||
|
||||
Never trust client-side:
|
||||
|
||||
- Subscription status.
|
||||
- Permissions.
|
||||
- Limits.
|
||||
|
||||
Verify server-side.
|
||||
|
||||
---
|
||||
|
||||
# Admin Features
|
||||
|
||||
Protect:
|
||||
|
||||
- User management.
|
||||
- AI providers.
|
||||
- System settings.
|
||||
|
||||
---
|
||||
|
||||
# Principle
|
||||
|
||||
Prepare architecture without adding unnecessary complexity early.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Current security notes
|
||||
|
||||
## Verified locally
|
||||
|
||||
- Tenant isolation, authorization replay, session revocation, upload/parser boundaries, AI sidecar token checks, PDF admission, and high-severity dependency gates have focused regression coverage.
|
||||
- The AI service is not published to the host in the production Compose topology; only the backend joins its private network.
|
||||
- Production Compose requires an AI service token and enables backend authentication by default.
|
||||
|
||||
## Requires external or manual verification
|
||||
|
||||
- Trusted proxy/ingress CIDRs, host firewall closure, TLS/redirect behavior, and production network topology.
|
||||
- Authenticated production smoke tests, real OAuth/provider behavior, email delivery, backup/restore, rollback, and key custody.
|
||||
- Full keyboard/screen-reader/zoom review of the CV builder and complete production UI console cleanliness.
|
||||
- Account-deletion retention policy, tombstone protection, and restored-backup erasure behavior.
|
||||
|
||||
These are not claims of resolved security findings. Dated evidence and the detailed P1/P2 audit packet are archived under `docs/_archive/pre-docs-cleanup-2026-09-11/docs/audits/` and the pre-existing archive.
|
||||
@@ -0,0 +1,5 @@
|
||||
# Sessions and rate limits
|
||||
|
||||
Session cookies are HttpOnly and SameSite=Lax, with Secure behavior controlled by deployment. Mutating cookie-authenticated requests use a CSRF double-submit cookie/header check. Users can list and revoke sessions; logout clears local client state.
|
||||
|
||||
Dedicated fixed-window limits cover login, authentication email, two-factor challenges, and anonymous public-CV PDF export. AI usage is bounded by account/monthly generation and token policy. Rate limits are a security and capacity control; do not loosen them to mask provider or UI failures.
|
||||
@@ -1,40 +0,0 @@
|
||||
# Supply-chain and credential scanning policy
|
||||
|
||||
## Required repository gates
|
||||
|
||||
Pull requests and `main` builds must pass all of the following without silently excluding a project:
|
||||
|
||||
- locked NuGet restore for the API and test project;
|
||||
- `npm ci` plus the configured high-severity audit gate;
|
||||
- hash-required installation of the Linux Python lock;
|
||||
- the package-manager advisory checks recorded in CI;
|
||||
- `python3 scripts/supply-chain.py scan-secrets` over every Git-tracked file; and
|
||||
- `python3 scripts/supply-chain.py generate-sbom --output .artifacts/jobjakt.cdx.json`.
|
||||
|
||||
The generated CycloneDX 1.5 SBOM combines the committed npm, NuGet and Python lock files. It is a build artifact, not a replacement for the locks or an image scan. Its lock digest and deterministic component ordering make dependency changes reviewable without adding generated files to source control.
|
||||
|
||||
The built-in tracked-secret scanner is deliberately high confidence. It detects private-key headers and recognizable JWT, AWS, GitHub, Google, Slack and live Stripe credentials, skips binary files and files over 2 MiB, and reports only the credential class and file location. It never prints a matched value. This gate complements—not replaces—host secret management, history review and a dedicated scanner when one is approved.
|
||||
|
||||
## Dependency and advisory exceptions
|
||||
|
||||
High or critical reachable advisories block release. An exception must be a reviewed repository document containing the package and affected path, advisory identifiers, reachability evidence, compensating control, accountable owner, expiry date and removal condition. Expired or ownerless exceptions fail closed. A version pin alone is not an exception.
|
||||
|
||||
The outstanding Torch/Transformers findings are not accepted exceptions. Their model-loading path and production image remain blocked pending a compatible resolution or a bounded, reviewed isolation decision.
|
||||
|
||||
## Immutable inputs
|
||||
|
||||
Third-party workflow actions, container bases and downloaded installers must move only to identifiers verified from their authoritative upstream source. Do not guess a commit SHA, image digest or installer checksum. Updates are reviewed commits and retain the prior known-good identifier for rollback.
|
||||
|
||||
The current mutable action/image references and `dotnet-install.sh` download remain open until network-backed upstream metadata and a container scanner are available. The local SBOM and tracked-secret gates do not claim to close those items.
|
||||
|
||||
## Credential response
|
||||
|
||||
If the tracked scan or a reviewer finds a real credential:
|
||||
|
||||
1. stop the affected build and suppress the value from chat, tickets and logs;
|
||||
2. revoke or rotate it at the issuing system before treating source cleanup as sufficient;
|
||||
3. remove it from the current tree and add the narrow prevention rule or ignore boundary needed;
|
||||
4. assess reachable history and CI artifacts using filenames/commit IDs only; and
|
||||
5. coordinate any history rewrite separately because it disrupts clones and does not revoke a credential.
|
||||
|
||||
Never weaken a detector merely to make an unexplained finding pass.
|
||||
@@ -1,82 +0,0 @@
|
||||
# Two Factor Authentication
|
||||
|
||||
## Purpose
|
||||
|
||||
Provide additional account protection.
|
||||
|
||||
---
|
||||
|
||||
# Preferred Method
|
||||
|
||||
TOTP authentication.
|
||||
|
||||
Compatible with:
|
||||
|
||||
- Google Authenticator.
|
||||
- Microsoft Authenticator.
|
||||
- Authy.
|
||||
|
||||
---
|
||||
|
||||
# Flow
|
||||
|
||||
Enable 2FA:
|
||||
|
||||
User requests setup
|
||||
|
||||
↓
|
||||
|
||||
Generate secret
|
||||
|
||||
↓
|
||||
|
||||
Display QR code
|
||||
|
||||
↓
|
||||
|
||||
User scans
|
||||
|
||||
↓
|
||||
|
||||
User confirms code
|
||||
|
||||
↓
|
||||
|
||||
Enable 2FA
|
||||
|
||||
---
|
||||
|
||||
# Login Flow
|
||||
|
||||
Password/OAuth
|
||||
|
||||
↓
|
||||
|
||||
Request authenticator code
|
||||
|
||||
↓
|
||||
|
||||
Validate
|
||||
|
||||
↓
|
||||
|
||||
Login
|
||||
|
||||
---
|
||||
|
||||
# Recovery
|
||||
|
||||
Support:
|
||||
|
||||
- Backup codes.
|
||||
- Disable/reset through account recovery.
|
||||
|
||||
---
|
||||
|
||||
# UX Requirements
|
||||
|
||||
Explain clearly:
|
||||
|
||||
- Why enable 2FA.
|
||||
- How it works.
|
||||
- Recovery options.
|
||||
@@ -1,8 +0,0 @@
|
||||
# uploads
|
||||
|
||||
Uploads are tenant-scoped through their parent application. File names are normalized with
|
||||
`Path.GetFileName` and stored under generated names inside the configured attachments root. The API
|
||||
enforces allowed types, a per-file size limit, and the account's total storage entitlement.
|
||||
|
||||
Downloads resolve the owned database record before opening a file. Files selected for AI are explicit;
|
||||
uploading alone does not send content to a provider.
|
||||
@@ -1,48 +0,0 @@
|
||||
# User Data Protection
|
||||
|
||||
## Purpose
|
||||
|
||||
Protect personal career information.
|
||||
|
||||
---
|
||||
|
||||
# Stored Data
|
||||
|
||||
Potential sensitive information:
|
||||
|
||||
- CV content.
|
||||
- Employment history.
|
||||
- Contact information.
|
||||
- Documents.
|
||||
- Email communication.
|
||||
|
||||
---
|
||||
|
||||
# Requirements
|
||||
|
||||
Support:
|
||||
|
||||
- User export.
|
||||
- User deletion.
|
||||
- Data ownership.
|
||||
|
||||
---
|
||||
|
||||
# Database
|
||||
|
||||
Ensure:
|
||||
|
||||
- Correct relationships.
|
||||
- No cross-user queries.
|
||||
- Safe migrations.
|
||||
|
||||
---
|
||||
|
||||
# Logging
|
||||
|
||||
Never log:
|
||||
|
||||
- Passwords.
|
||||
- Tokens.
|
||||
- Private documents.
|
||||
- Sensitive CV content.
|
||||
@@ -1,8 +0,0 @@
|
||||
# validation
|
||||
|
||||
Validation happens at trust boundaries: controller request DTOs, file uploads, imported URLs, OAuth
|
||||
state callbacks, AI sidecar authentication, and deployment configuration. Job import and IMAP targets
|
||||
resolve through SSRF guards that reject private, loopback, link-local, and unsafe redirect targets.
|
||||
|
||||
Unhandled failures use Problem Details with a trace ID; expected validation failures retain their
|
||||
specific 4xx responses. See `docs/security/input-validation.md` and `docs/security/api-security.md`.
|
||||
Reference in New Issue
Block a user