Commit Graph

8 Commits

Author SHA1 Message Date
cesnimda c0bf69ad56 fix(security): enforce explicit api authorization
CI and Deploy / test (push) Failing after 1m10s
CI and Deploy / deploy (push) Has been skipped
Authentication relied on a fallback policy gated on Auth:Require, which defaults
to false. Five user-owned controllers carried no [Authorize] of their own, so a
deployment that lost that flag would have served tenant data anonymously:
JobApplications, Companies, Correspondence, Rules and JobImport. All five now
declare [Authorize(AuthenticationSchemes = "local")] explicitly.

This does not affect local development, which already sets Auth:Require=true in
appsettings.Development.json — the gap was only ever in a production
configuration that omitted the flag.

Added a reflection test over every controller in the assembly so a new one
cannot ship unprotected by accident. A controller passes if the class requires
authorization, or if every action declares its own [Authorize] or
[AllowAnonymous] — the shape AuthController and TwoFactorController need, since
login and register must stay anonymous while the rest must not. Public endpoints
are an explicit allow-list, so making something anonymous is now a deliberate
edit rather than an omission.

That test found one real gap: AuthController.Logout declared neither attribute.
It is now explicitly [AllowAnonymous] — it only clears the caller's own session
cookies and leaks nothing, and requiring authentication would leave a user whose
token had already expired unable to sign out.

Also pinned: admin controllers require the Admin role rather than merely a
signed-in user, and PublicCvController stays anonymous so shared CV links keep
working.

384 backend tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 17:27:27 +02:00
cesnimda cb2715c323 feat(email): add Correspondence.Provider discriminator
CI and Deploy / test (pull_request) Successful in 2m2s
CI and Deploy / deploy (pull_request) Has been skipped
b4 of the multi-provider email roadmap. The manual/free-text correspondence
entry path already existed (CorrespondenceController.Create) -- this slice
was narrower than the roadmap wording suggests: tag every Correspondence row
with which provider it came from (gmail | manual today; microsoft | imap
once those providers grow an import-into-Correspondence path of their own),
not build a new endpoint.

- Correspondence.Provider (nullable string), reconciled via the existing
  EnsureColumn pattern (SQLite + MySQL).
- Idempotent backfill: rows with an ExternalThreadId (historically only
  ever written by Gmail import) get 'gmail'; everything else gets 'manual'.
- GmailController.ImportSingleMessageAsync now tags Provider = "gmail".
- CorrespondenceController.Create now tags Provider = "manual".
- Both write sites use a fixed literal, not request input -- no injection
  surface introduced. Backfill SQL is static, no interpolation.

148/148 green (147 existing + 1 new CorrespondenceControllerTests; the
GmailController import test gained a Provider assertion in place).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 19:47:52 +02:00
cesnimda 3f04849fe6 feat: add correspondence inbox and gmail ingestion contract 2026-04-01 16:50:14 +02:00
cesnimda f48136f04c feat: enrich gmail correspondence metadata 2026-04-01 16:27:34 +02:00
cesnimda 3e5f796326 Complete S01 Gmail matching and import workflow 2026-03-24 10:06:50 +01:00
cesnimda a974e80ca4 fix: enforce ownership checks for attachments and correspondence 2026-03-22 14:00:24 +01:00
cesnimda 5ed5b340a5 Feature: Remove message, Upgrade: pull better job data, add dedicated status section to job applications 2026-03-21 21:04:04 +01:00
cesnimda 2e8a29b4d0 First Commit 2026-03-21 11:55:27 +01:00