Skip to content

Commit 5710c54

Browse files
authored
Merge pull request #42 from rhysmcneill/feature/hmrc-compliance
Feature/hmrc compliance
2 parents e76ba49 + 54797f7 commit 5710c54

22 files changed

Lines changed: 650 additions & 70 deletions

.dockerignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ node_modules/
1818
vendor/
1919

2020
# Docker secrets
21-
docker/secrets/*.txt
21+
docker/secrets/*
2222

2323
# CSS output (generated file)
2424
web/static/css/output.css

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docker/secrets/** filter=git-crypt diff=git-crypt

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ tmp/
2525
.air.toml
2626

2727
# Docker secrets
28-
docker/secrets/*.txt
28+
docker/secrets/
2929

3030
# HMRC files
3131
docs/*.json

.gitleaks.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
title = "Dividr Gitleaks Config"
2+
3+
[extend]
4+
useDefault = true
5+
6+
# Block specific paths - these should NEVER contain secrets
7+
[[rules]]
8+
id = "block-secrets-folder"
9+
description = "Prevent committing docker/secrets/ directory"
10+
path = '''docker/secrets/'''
11+
12+
[[rules]]
13+
id = "block-test-data"
14+
description = "Prevent committing test data with credentials"
15+
path = '''docs/.*\.json$'''

.pre-commit-config.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@ repos:
2929
pass_filenames: false
3030
files: \.go$
3131

32+
- id: block-secrets-folder
33+
name: Block docker/secrets/ directory
34+
entry: bash -c 'if git diff --cached --name-only | grep -q "^docker/secrets/"; then echo "ERROR - Files in docker/secrets/ should never be committed!"; exit 1; fi'
35+
language: system
36+
pass_filenames: false
37+
always_run: true
38+
39+
- id: block-test-data
40+
name: Block test data files
41+
entry: bash -c 'if git diff --cached --name-only | grep -qE "^docs/.*\.json$"; then echo "ERROR - Test data files in docs/ should never be committed!"; exit 1; fi'
42+
language: system
43+
pass_filenames: false
44+
always_run: true
45+
3246
# General file quality
3347
- repo: https://github.com/pre-commit/pre-commit-hooks
3448
rev: v2.3.0

internal/config/config.go

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,41 @@ import (
1212
)
1313

1414
type Config struct {
15-
AppEnv string
16-
Port string
17-
DatabaseURL string
18-
LogLevel string
19-
DBMaxConns int // Default: 10
20-
DBMinConns int // Default: 2
21-
DBMaxConnIdle time.Duration // Default: 30 minutes
22-
HMRCRedirectURL string
23-
HMRCClientID string
24-
HMRCClientSecret string
15+
AppEnv string
16+
Port string
17+
DatabaseURL string
18+
LogLevel string
19+
DBMaxConns int // Default: 10
20+
DBMinConns int // Default: 2
21+
DBMaxConnIdle time.Duration // Default: 30 minutes
22+
HMRCRedirectURL string
23+
HMRCClientID string
24+
HMRCClientSecret string
25+
TokenEncryptionKey string
2526
}
2627

2728
func Load() *Config {
2829
// Load .env file if it exists (silently fails if not found)
2930
_ = godotenv.Load()
3031

3132
return &Config{
32-
AppEnv: getEnv("APP_ENV", "dev"),
33-
Port: getEnv("PORT", "8080"),
34-
DatabaseURL: buildDatabaseURL(),
35-
LogLevel: getEnv("LOG_LEVEL", "DEBUG"),
36-
DBMaxConns: getEnvInt("DB_MAX_CONNS", 10),
37-
DBMinConns: getEnvInt("DB_MIN_CONNS", 2),
38-
DBMaxConnIdle: getEnvDuration("DB_MAX_CONN_IDLE", 30*time.Minute),
39-
HMRCRedirectURL: getEnv("HMRC_REDIRECT_URL", "http://localhost:8080/auth/hmrc/callback"),
40-
HMRCClientID: getEnv("HMRC_CLIENT_ID", ""),
41-
HMRCClientSecret: getHMRCCLientSecret(),
33+
AppEnv: getEnv("APP_ENV", "dev"),
34+
Port: getEnv("PORT", "8080"),
35+
DatabaseURL: buildDatabaseURL(),
36+
LogLevel: getEnv("LOG_LEVEL", "DEBUG"),
37+
DBMaxConns: getEnvInt("DB_MAX_CONNS", 10),
38+
DBMinConns: getEnvInt("DB_MIN_CONNS", 2),
39+
DBMaxConnIdle: getEnvDuration("DB_MAX_CONN_IDLE", 30*time.Minute),
40+
HMRCRedirectURL: getEnv("HMRC_REDIRECT_URL", "http://localhost:8080/auth/hmrc/callback"),
41+
HMRCClientID: getEnv("HMRC_CLIENT_ID", ""),
42+
HMRCClientSecret: getHMRCCLientSecret(),
43+
TokenEncryptionKey: getCryptoKey(),
4244
}
4345
}
4446

4547
func getEnv(key, defaultValue string) string {
4648
if value, exists := os.LookupEnv(key); exists {
47-
return value
49+
return strings.TrimSpace(value)
4850
}
4951
return defaultValue
5052
}
@@ -112,6 +114,27 @@ func getHMRCCLientSecret() string {
112114
return getEnv("HMRC_CLIENT_SECRET", "")
113115
}
114116

117+
func getCryptoKey() string {
118+
// Try Docker secret first
119+
secretPath := "/run/secrets/crypto_key"
120+
if data, err := os.ReadFile(secretPath); err == nil {
121+
return strings.TrimSpace(string(data))
122+
}
123+
124+
// Try local file for development convenience
125+
localSecretPath := "docker/secrets/.crypto_key"
126+
if data, err := os.ReadFile(localSecretPath); err == nil {
127+
return strings.TrimSpace(string(data))
128+
}
129+
cwd, _ := os.Getwd()
130+
slog.Info("debug: attempting to load secret",
131+
"current_dir", cwd,
132+
"target_path", localSecretPath,
133+
)
134+
// Fallback to env var
135+
return getEnv("TOKEN_ENCRYPTION_KEY", "")
136+
}
137+
115138
// getEnvInt reads an integer from env or returns default
116139
func getEnvInt(key string, defaultVal int) int {
117140
if v, exists := os.LookupEnv(key); exists {

internal/database/audit.sql.go

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/database/database.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ func Connect(cfg *config.Config) (*Service, error) {
2828
return nil, fmt.Errorf("unable to connect to database: %w", err)
2929
}
3030

31+
pool.Config().MaxConns = int32(cfg.DBMaxConns)
32+
pool.Config().MinConns = int32(cfg.DBMinConns)
33+
pool.Config().MaxConnIdleTime = cfg.DBMaxConnIdle
34+
3135
// 2. Fast Ping to verify
3236
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
3337
defer cancel()

internal/database/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- name: CreateAuditEvent :one
2+
INSERT INTO audit_events (
3+
user_id,
4+
event_type,
5+
ip_address,
6+
details
7+
) VALUES (
8+
$1, $2, $3, $4
9+
) RETURNING id, created_at;

0 commit comments

Comments
 (0)