* infra(terraform): manage finance session secret via random_password
Replace the hand-rolled variable (with insecure hardcoded default) with a
random_password resource so Terraform auto-generates a 48-char secret and
owns the finance-api-secrets k8s Secret lifecycle.
To rotate: terraform taint random_password.finance_session_secret && terraform apply
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(finance): active sessions panel + account deletion with full data purge
Sessions panel (/account):
- AuthSession now stores IPAddress and Device (browser + OS hint)
populated from X-Forwarded-For / User-Agent on every login
- Lists all active sessions with device icon, IP, sign-in time
- Current session badge ("This device") — cannot be self-revoked
- DELETE /sessions/:id revokes any other session (user-scoped)
Account deletion (POST /account/delete):
- Password accounts require password confirmation
- OAuth accounts require typing email address to confirm
- deleteAllUserData purges all 12 finance collections + user record
in a single call: accounts, categories, transactions, trades,
ticker_mappings, goals, import_schedules, properties, loans,
permissions, households, sessions → then the user itself
- Clears session cookie and redirects to login with success message
Infrastructure:
- findAuthUserByID added to store + storeIface
- getSessionsByUserID, deleteSessionForUser added to store + storeIface
- contains() added to template FuncMap
- accountTmpl registered; GET /account, POST /account/delete,
DELETE /sessions/:id routes wired
- 🔐 nav icon links to /account page
- Full EN + PT i18n coverage for all new strings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(finance): expand unit test coverage from ~55% to 64.7%
- Add handler_coverage_test.go (~3300 lines) covering auth flows,
org request lifecycle, CSV bank import, property/loan views,
fiscal year operations, session management, and cross-handler
consistency (values shown on one page match actions on others)
- Add handler_org_test.go (~1800 lines) covering the full org
handler surface: teams, members, invites, events, budget lines,
tx requests (all status transitions), ledger, analysis, and reports
- Extend handler_test.go mockStore with: properties/loans slice fields,
authUsers map with session-aware lookup, household field, org maps,
and updateFiscalYearStatusErr for error-path testing
- Fix nav bar: Business and Account links now show active state and
use i18n keys (removes hardcoded emoji); add account key to en/pt locales
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Gonçalo Rodrigues <guga@Goncalos-MacBook-Pro.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
33 lines
1.0 KiB
HCL
33 lines
1.0 KiB
HCL
# Session secret is auto-generated and stored in Terraform state (gitignored).
|
|
# To rotate: terraform taint random_password.finance_session_secret && terraform apply
|
|
resource "random_password" "finance_session_secret" {
|
|
length = 48
|
|
special = false # alphanumeric only — safe as an env var value
|
|
}
|
|
|
|
variable "finance_google_client_id" {
|
|
description = "Google OAuth client ID for finance-api (optional)"
|
|
type = string
|
|
default = ""
|
|
sensitive = false
|
|
}
|
|
|
|
variable "finance_google_client_secret" {
|
|
description = "Google OAuth client secret for finance-api (optional)"
|
|
type = string
|
|
default = ""
|
|
sensitive = true
|
|
}
|
|
|
|
resource "kubernetes_secret" "finance_api" {
|
|
metadata {
|
|
name = "finance-api-secrets"
|
|
namespace = kubernetes_namespace.domains["finance"].metadata[0].name
|
|
}
|
|
data = {
|
|
SESSION_SECRET = random_password.finance_session_secret.result
|
|
GOOGLE_CLIENT_ID = var.finance_google_client_id
|
|
GOOGLE_CLIENT_SECRET = var.finance_google_client_secret
|
|
}
|
|
}
|