docs: project docs, scripts, deployment configs, and evidence

This commit is contained in:
2026-04-02 11:22:17 +08:00
parent 4718980ab5
commit bbeeb63dfa
396 changed files with 165018 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
# Alertmanager Render Drill
- Generated at: 2026-03-24 10:25:54 +08:00
- Template file: D:\project\deployment\alertmanager\alertmanager.yml
- Rendered file: D:\project\docs\evidence\ops\2026-03-24\alerting\20260324-102553\alertmanager.rendered.yaml
- Synthetic secret values were injected through process environment variables for this drill only.
- Result: template placeholders resolved successfully and the rendered config contains no unresolved `${ALERTMANAGER_*}` tokens.
## Scope Note
- This drill validates the config injection/rendering path only.
- It does not prove real SMTP delivery, real contact routing, or production secret manager integration.
## Evidence Files
- alertmanager.rendered.yaml

View File

@@ -0,0 +1,85 @@
global:
resolve_timeout: 5m
# 注意:
# 该文件为模板文件,生产环境必须先注入并渲染 `${ALERTMANAGER_*}` 变量,
# 再将渲染结果交给 Alertmanager 使用。
# 告警路由
route:
group_by: ['alertname', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
receiver: 'default'
# 子路由,根据严重级别分发
routes:
# Critical 告警
- match:
severity: critical
receiver: 'critical-alerts'
group_wait: 10s
continue: true
# Warning 告警
- match:
severity: warning
receiver: 'warning-alerts'
continue: true
# 告警接收者
receivers:
# 默认接收者
- name: 'default'
email_configs:
- to: 'ops-team@example.org'
from: 'alertmanager@example.org'
smarthost: 'smtp.example.org:587'
auth_username: 'alertmanager@example.org'
auth_password: 'synthetic-secret-for-render-drill'
headers:
Subject: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
# Critical 告警接收者
- name: 'critical-alerts'
email_configs:
- to: 'critical-oncall@example.org'
from: 'alertmanager@example.org'
smarthost: 'smtp.example.org:587'
auth_username: 'alertmanager@example.org'
auth_password: 'synthetic-secret-for-render-drill'
headers:
Subject: '[CRITICAL] {{ .GroupLabels.alertname }}'
# Warning 告警接收者
- name: 'warning-alerts'
email_configs:
- to: 'warning-oncall@example.org'
from: 'alertmanager@example.org'
smarthost: 'smtp.example.org:587'
auth_username: 'alertmanager@example.org'
auth_password: 'synthetic-secret-for-render-drill'
headers:
Subject: '[WARNING] {{ .GroupLabels.alertname }}'
# 告警抑制规则
inhibit_rules:
# 如果有 critical 告警,抑制同一服务的 warning 告警
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['service']
# 告警静默规则(按需配置)
# silences:
# - matchers:
# - name: alertname
# value: LowOnlineUsers
# - name: severity
# value: info
# startsAt: "2026-03-12T00:00:00+08:00"
# endsAt: "2026-03-12T23:59:59+08:00"
# comment: "维护期间静默低在线用户告警"

View File

@@ -0,0 +1,34 @@
# Alerting Package Validation
- Generated at: 2026-03-24 10:13:07 +08:00
- Alerts file: D:\project\deployment\alertmanager\alerts.yml
- Alertmanager file: D:\project\deployment\alertmanager\alertmanager.yml
- Baseline report: D:\project\docs\evidence\ops\2026-03-24\observability\LOCAL_BASELINE_20260324-090637.md
## Structural Validation
- Rule inventory: critical=3, warning=4, info=2
- Missing required rules: none
- Root receiver: default
- Critical route receiver: critical-alerts
- Warning route receiver: warning-alerts
- Missing required receivers: none
- Structural ready: True
## Threshold Alignment
- HighResponseTime threshold: 1s
- Latest browser max baseline: 242ms
- Latest browser timings: login-desktop=242ms, login-initial=98ms, login-mobile=90ms, login-tablet=100ms
## External Delivery Readiness
- Placeholder findings: admin@example\.com, ops-team@example\.com, dev-team@example\.com, alertmanager@example\.com, smtp\.example\.com, auth_password:\s*'password'
- External delivery closed: False
- Interpretation: rules and route topology can be reviewed locally, but example SMTP/accounts mean real notification delivery evidence is still open until environment-specific contacts and secrets are injected.
## Conclusion
- Repo-level alerting package structurally ready: True
- Repo-level oncall/delivery package fully closed: False

View File

@@ -0,0 +1,34 @@
# Alerting Package Validation
- Generated at: 2026-03-24 10:25:40 +08:00
- Alerts file: D:\project\deployment\alertmanager\alerts.yml
- Alertmanager file: D:\project\deployment\alertmanager\alertmanager.yml
- Baseline report: D:\project\docs\evidence\ops\2026-03-24\observability\LOCAL_BASELINE_20260324-090637.md
## Structural Validation
- Rule inventory: critical=3, warning=4, info=2
- Missing required rules: none
- Root receiver: default
- Critical route receiver: critical-alerts
- Warning route receiver: warning-alerts
- Missing required receivers: none
- Structural ready: True
## Threshold Alignment
- HighResponseTime threshold: 1s
- Latest browser max baseline: 242ms
- Latest browser timings: login-desktop=242ms, login-initial=98ms, login-mobile=90ms, login-tablet=100ms
## External Delivery Readiness
- Placeholder findings: \$\{ALERTMANAGER_[A-Z0-9_]+\}
- External delivery closed: False
- Interpretation: rules and route topology can be reviewed locally, but unresolved template variables or example SMTP/accounts mean real notification delivery evidence is still open until environment-specific contacts and secrets are injected.
## Conclusion
- Repo-level alerting package structurally ready: True
- Repo-level oncall/delivery package fully closed: False

View File

@@ -0,0 +1,39 @@
# Backup Restore Drill
- Generated at: 2026-03-24 07:23:14 +08:00
- Source DB: $SourceDb
- Backup DB: $backupDb
- Restored DB: $restoredDb
- Probe port: 18080
## Hash Validation
- source sha256: $sourceHash
- backup sha256: $backupHash
- restored sha256: $restoredHash
## Snapshot Comparison
- source tables: $sourceTablesJson
- restored tables: $restoredTablesJson
- source existing tables: $((devices login_logs operation_logs password_histories permissions role_permissions roles sqlite_sequence user_roles user_social_accounts users webhook_deliveries webhooks -join ', '))
- restored existing tables: $((devices login_logs operation_logs password_histories permissions role_permissions roles sqlite_sequence user_roles user_social_accounts users webhook_deliveries webhooks -join ', '))
- source missing tables: $(if (social_accounts.Count -gt 0) { social_accounts -join ', ' } else { 'none' })
- restored missing tables: $(if (social_accounts.Count -gt 0) { social_accounts -join ', ' } else { 'none' })
- sample users: $((@{generated_at=2026-03-24T07:23:07+08:00; path=D:\project\data\user_management.db; file_size=172032; existing_tables=System.Object[]; missing_tables=System.Object[]; tables=; sample_users=System.Object[]}.SampleUsers -join ', '))
## Restore Service Verification
- GET /health: pass
- GET /health/ready: pass
- GET /api/v1/auth/capabilities: pass
- auth capabilities payload: $((@{code=0; message=success; data=}.data | ConvertTo-Json -Compress))
## Evidence Files
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\backup-restore\20260324-072304\source-snapshot.json -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\backup-restore\20260324-072304\restored-snapshot.json -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\backup-restore\20260324-072304\server.stdout.log -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\backup-restore\20260324-072304\server.stderr.log -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\backup-restore\20260324-072304\config.restore.yaml -Leaf)

View File

@@ -0,0 +1,215 @@
server:
port: 18080
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # sqlite, postgresql, mysql
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/backup-restore/20260324-072304/user_management.restored.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: password
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: password
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: your-secret-key-change-in-production
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7澶?= 168灏忔椂
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "http://127.0.0.1:3000"
allowed_methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- X-Requested-With
- X-CSRF-Token
max_age: 3600
email:
host: "" # 鐢熶骇鐜濉啓鐪熷疄 SMTP Host
port: 18080
username: ""
password: ""
from_email: ""
from_name: "鐢ㄦ埛绠$悊绯荤粺"
sms:
enabled: false
provider: "" # aliyun, tencent锛涚暀绌鸿〃绀虹鐢ㄧ煭淇¤兘鍔? code_ttl: 5m
resend_cooldown: 1m
max_daily_limit: 10
aliyun:
access_key_id: ""
access_key_secret: ""
sign_name: ""
template_code: ""
endpoint: ""
region_id: "cn-hangzhou"
code_param_name: "code"
tencent:
secret_id: ""
secret_key: ""
app_id: ""
sign_name: ""
template_id: ""
region: "ap-guangzhou"
endpoint: ""
password_reset:
token_ttl: 15m
site_url: "http://localhost:8080"
# OAuth 绀句氦鐧诲綍閰嶇疆锛堢暀绌哄垯绂佺敤瀵瑰簲 Provider锛?
oauth:
google:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/google/callback"
wechat:
app_id: ""
app_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/wechat/callback"
github:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/github/callback"
qq:
app_id: ""
app_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/qq/callback"
alipay:
app_id: ""
private_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/alipay/callback"
sandbox: false
douyin:
client_key: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/douyin/callback"
# Webhook 鍏ㄥ眬閰嶇疆
webhook:
enabled: true
secret_header: "X-Webhook-Signature" # 绛惧悕 Header 鍚嶇О
timeout_sec: 30 # 鍗曟鎶曢€掕秴鏃讹紙绉掞級
max_retries: 3 # 鏈€澶ч噸璇曟鏁?
retry_backoff: "exponential" # 閫€閬跨瓥鐣ワ細exponential / fixed
worker_count: 4 # 鍚庡彴鎶曢€掑崗绋嬫暟
queue_size: 1000 # 鎶曢€掗槦鍒楀ぇ灏?
# IP 瀹夊叏閰嶇疆
ip_security:
auto_block_enabled: true # 鏄惁鍚敤鑷姩灏佺
auto_block_duration: 30m # 鑷姩灏佺鏃堕暱
brute_force_threshold: 10 # 鏆村姏鐮磋В闃堝€硷紙绐楀彛鍐呭け璐ユ鏁帮級
detection_window: 15m # 妫€娴嬫椂闂寸獥鍙?

View File

@@ -0,0 +1,40 @@
{
"generated_at": "2026-03-24T07:23:08+08:00",
"path": "D:\\project\\docs\\evidence\\ops\\2026-03-24\\backup-restore\\20260324-072304\\user_management.restored.db",
"file_size": 172032,
"existing_tables": [
"devices",
"login_logs",
"operation_logs",
"password_histories",
"permissions",
"role_permissions",
"roles",
"sqlite_sequence",
"user_roles",
"user_social_accounts",
"users",
"webhook_deliveries",
"webhooks"
],
"missing_tables": [
"social_accounts"
],
"tables": {
"devices": 0,
"login_logs": 2,
"operation_logs": 6,
"password_histories": 0,
"permissions": 17,
"role_permissions": 20,
"roles": 2,
"user_roles": 1,
"users": 1,
"webhook_deliveries": 0,
"webhooks": 0
},
"sample_users": [
"e2e_admin"
]
}

View File

@@ -0,0 +1,40 @@
{
"generated_at": "2026-03-24T07:23:07+08:00",
"path": "D:\\project\\data\\user_management.db",
"file_size": 172032,
"existing_tables": [
"devices",
"login_logs",
"operation_logs",
"password_histories",
"permissions",
"role_permissions",
"roles",
"sqlite_sequence",
"user_roles",
"user_social_accounts",
"users",
"webhook_deliveries",
"webhooks"
],
"missing_tables": [
"social_accounts"
],
"tables": {
"devices": 0,
"login_logs": 2,
"operation_logs": 6,
"password_histories": 0,
"permissions": 17,
"role_permissions": 20,
"roles": 2,
"user_roles": 1,
"users": 1,
"webhook_deliveries": 0,
"webhooks": 0
},
"sample_users": [
"e2e_admin"
]
}

View File

@@ -0,0 +1,39 @@
# Backup Restore Drill
- Generated at: 2026-03-24 07:24:00 +08:00
- Source DB: D:\project\data\user_management.db
- Backup DB: D:\project\docs\evidence\ops\2026-03-24\backup-restore\20260324-072353\user_management.backup.db
- Restored DB: D:\project\docs\evidence\ops\2026-03-24\backup-restore\20260324-072353\user_management.restored.db
- Probe port: 18080
## Hash Validation
- source sha256: FFC7A3326BF4C57569FC0E5429206971E122846ADEF1DE167E1B81CED9D8E0F4
- backup sha256: FFC7A3326BF4C57569FC0E5429206971E122846ADEF1DE167E1B81CED9D8E0F4
- restored sha256: FFC7A3326BF4C57569FC0E5429206971E122846ADEF1DE167E1B81CED9D8E0F4
## Snapshot Comparison
- source tables: {"devices":0,"login_logs":2,"operation_logs":6,"password_histories":0,"permissions":17,"role_permissions":20,"roles":2,"user_roles":1,"users":1,"webhook_deliveries":0,"webhooks":0}
- restored tables: {"devices":0,"login_logs":2,"operation_logs":6,"password_histories":0,"permissions":17,"role_permissions":20,"roles":2,"user_roles":1,"users":1,"webhook_deliveries":0,"webhooks":0}
- source existing tables: devices, login_logs, operation_logs, password_histories, permissions, role_permissions, roles, sqlite_sequence, user_roles, user_social_accounts, users, webhook_deliveries, webhooks
- restored existing tables: devices, login_logs, operation_logs, password_histories, permissions, role_permissions, roles, sqlite_sequence, user_roles, user_social_accounts, users, webhook_deliveries, webhooks
- source missing tables: social_accounts
- restored missing tables: social_accounts
- sample users: e2e_admin
## Restore Service Verification
- GET /health: pass
- GET /health/ready: pass
- GET /api/v1/auth/capabilities: pass
- auth capabilities payload: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
## Evidence Files
- source-snapshot.json
- restored-snapshot.json
- server.stdout.log
- server.stderr.log
- config.restore.yaml

View File

@@ -0,0 +1,215 @@
server:
port: 18080
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # sqlite, postgresql, mysql
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/backup-restore/20260324-072353/user_management.restored.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: password
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: password
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: your-secret-key-change-in-production
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7澶?= 168灏忔椂
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "http://127.0.0.1:3000"
allowed_methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- X-Requested-With
- X-CSRF-Token
max_age: 3600
email:
host: "" # 鐢熶骇鐜濉啓鐪熷疄 SMTP Host
port: 18080
username: ""
password: ""
from_email: ""
from_name: "鐢ㄦ埛绠$悊绯荤粺"
sms:
enabled: false
provider: "" # aliyun, tencent锛涚暀绌鸿〃绀虹鐢ㄧ煭淇¤兘鍔? code_ttl: 5m
resend_cooldown: 1m
max_daily_limit: 10
aliyun:
access_key_id: ""
access_key_secret: ""
sign_name: ""
template_code: ""
endpoint: ""
region_id: "cn-hangzhou"
code_param_name: "code"
tencent:
secret_id: ""
secret_key: ""
app_id: ""
sign_name: ""
template_id: ""
region: "ap-guangzhou"
endpoint: ""
password_reset:
token_ttl: 15m
site_url: "http://localhost:8080"
# OAuth 绀句氦鐧诲綍閰嶇疆锛堢暀绌哄垯绂佺敤瀵瑰簲 Provider锛?
oauth:
google:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/google/callback"
wechat:
app_id: ""
app_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/wechat/callback"
github:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/github/callback"
qq:
app_id: ""
app_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/qq/callback"
alipay:
app_id: ""
private_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/alipay/callback"
sandbox: false
douyin:
client_key: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/douyin/callback"
# Webhook 鍏ㄥ眬閰嶇疆
webhook:
enabled: true
secret_header: "X-Webhook-Signature" # 绛惧悕 Header 鍚嶇О
timeout_sec: 30 # 鍗曟鎶曢€掕秴鏃讹紙绉掞級
max_retries: 3 # 鏈€澶ч噸璇曟鏁?
retry_backoff: "exponential" # 閫€閬跨瓥鐣ワ細exponential / fixed
worker_count: 4 # 鍚庡彴鎶曢€掑崗绋嬫暟
queue_size: 1000 # 鎶曢€掗槦鍒楀ぇ灏?
# IP 瀹夊叏閰嶇疆
ip_security:
auto_block_enabled: true # 鏄惁鍚敤鑷姩灏佺
auto_block_duration: 30m # 鑷姩灏佺鏃堕暱
brute_force_threshold: 10 # 鏆村姏鐮磋В闃堝€硷紙绐楀彛鍐呭け璐ユ鏁帮級
detection_window: 15m # 妫€娴嬫椂闂寸獥鍙?

View File

@@ -0,0 +1,40 @@
{
"generated_at": "2026-03-24T07:23:55+08:00",
"path": "D:\\project\\docs\\evidence\\ops\\2026-03-24\\backup-restore\\20260324-072353\\user_management.restored.db",
"file_size": 172032,
"existing_tables": [
"devices",
"login_logs",
"operation_logs",
"password_histories",
"permissions",
"role_permissions",
"roles",
"sqlite_sequence",
"user_roles",
"user_social_accounts",
"users",
"webhook_deliveries",
"webhooks"
],
"missing_tables": [
"social_accounts"
],
"tables": {
"devices": 0,
"login_logs": 2,
"operation_logs": 6,
"password_histories": 0,
"permissions": 17,
"role_permissions": 20,
"roles": 2,
"user_roles": 1,
"users": 1,
"webhook_deliveries": 0,
"webhooks": 0
},
"sample_users": [
"e2e_admin"
]
}

View File

@@ -0,0 +1,40 @@
{
"generated_at": "2026-03-24T07:23:54+08:00",
"path": "D:\\project\\data\\user_management.db",
"file_size": 172032,
"existing_tables": [
"devices",
"login_logs",
"operation_logs",
"password_histories",
"permissions",
"role_permissions",
"roles",
"sqlite_sequence",
"user_roles",
"user_social_accounts",
"users",
"webhook_deliveries",
"webhooks"
],
"missing_tables": [
"social_accounts"
],
"tables": {
"devices": 0,
"login_logs": 2,
"operation_logs": 6,
"password_histories": 0,
"permissions": 17,
"role_permissions": 20,
"roles": 2,
"user_roles": 1,
"users": 1,
"webhook_deliveries": 0,
"webhooks": 0
},
"sample_users": [
"e2e_admin"
]
}

View File

@@ -0,0 +1,27 @@
# Config And Env Isolation Drill
- Generated at: 2026-03-24 08:49:21 +08:00
- Source DB: D:\project\data\user_management.db
- Isolated DB: D:\project\docs\evidence\ops\2026-03-24\config-isolation\20260324-084915\user_management.isolated.db
- Isolated config: D:\project\docs\evidence\ops\2026-03-24\config-isolation\20260324-084915\config.isolated.yaml
## Verification Results
- Base config default port: 8080
- UMS_CONFIG_PATH isolated port: 18085
- UMS_SERVER_PORT override port: 18086
- UMS_CORS_ALLOWED_ORIGINS override accepted origin: https://admin.example.com
- UMS_CORS_ALLOWED_ORIGINS override excluded origin: none
- auth capabilities with config-only override: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
- auth capabilities with env override: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
## Evidence Files
- config-only.stdout.log
- config-only.stderr.log
- env-override.stdout.log
- env-override.stderr.log
- capabilities.config-only.json
- capabilities.env-override.json
- config.isolated.yaml

View File

@@ -0,0 +1,10 @@
{
"password": true,
"email_code": false,
"sms_code": false,
"password_reset": false,
"oauth_providers": [
]
}

View File

@@ -0,0 +1,10 @@
{
"password": true,
"email_code": false,
"sms_code": false,
"password_reset": false,
"oauth_providers": [
]
}

View File

@@ -0,0 +1,215 @@
server:
port: 18085
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # sqlite, postgresql, mysql
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/config-isolation/20260324-084915/user_management.isolated.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: password
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: password
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: your-secret-key-change-in-production
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7澶?= 168灏忔椂
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "http://127.0.0.1:3000"
allowed_methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- X-Requested-With
- X-CSRF-Token
max_age: 3600
email:
host: "" # 鐢熶骇鐜濉啓鐪熷疄 SMTP Host
port: 18085
username: ""
password: ""
from_email: ""
from_name: "鐢ㄦ埛绠$悊绯荤粺"
sms:
enabled: false
provider: "" # aliyun, tencent锛涚暀绌鸿〃绀虹鐢ㄧ煭淇¤兘鍔? code_ttl: 5m
resend_cooldown: 1m
max_daily_limit: 10
aliyun:
access_key_id: ""
access_key_secret: ""
sign_name: ""
template_code: ""
endpoint: ""
region_id: "cn-hangzhou"
code_param_name: "code"
tencent:
secret_id: ""
secret_key: ""
app_id: ""
sign_name: ""
template_id: ""
region: "ap-guangzhou"
endpoint: ""
password_reset:
token_ttl: 15m
site_url: "http://localhost:8080"
# OAuth 绀句氦鐧诲綍閰嶇疆锛堢暀绌哄垯绂佺敤瀵瑰簲 Provider锛?
oauth:
google:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/google/callback"
wechat:
app_id: ""
app_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/wechat/callback"
github:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/github/callback"
qq:
app_id: ""
app_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/qq/callback"
alipay:
app_id: ""
private_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/alipay/callback"
sandbox: false
douyin:
client_key: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/douyin/callback"
# Webhook 鍏ㄥ眬閰嶇疆
webhook:
enabled: true
secret_header: "X-Webhook-Signature" # 绛惧悕 Header 鍚嶇О
timeout_sec: 30 # 鍗曟鎶曢€掕秴鏃讹紙绉掞級
max_retries: 3 # 鏈€澶ч噸璇曟鏁?
retry_backoff: "exponential" # 閫€閬跨瓥鐣ワ細exponential / fixed
worker_count: 4 # 鍚庡彴鎶曢€掑崗绋嬫暟
queue_size: 1000 # 鎶曢€掗槦鍒楀ぇ灏?
# IP 瀹夊叏閰嶇疆
ip_security:
auto_block_enabled: true # 鏄惁鍚敤鑷姩灏佺
auto_block_duration: 30m # 鑷姩灏佺鏃堕暱
brute_force_threshold: 10 # 鏆村姏鐮磋В闃堝€硷紙绐楀彛鍐呭け璐ユ鏁帮級
detection_window: 15m # 妫€娴嬫椂闂寸獥鍙?

View File

@@ -0,0 +1,27 @@
# Config And Env Isolation Drill
- Generated at: 2026-03-24 10:38:07 +08:00
- Source DB: D:\project\data\user_management.db
- Isolated DB: D:\project\docs\evidence\ops\2026-03-24\config-isolation\20260324-103758\user_management.isolated.db
- Isolated config: D:\project\docs\evidence\ops\2026-03-24\config-isolation\20260324-103758\config.isolated.yaml
## Verification Results
- Base config default port: 8080
- UMS_CONFIG_PATH isolated port: 18085
- UMS_SERVER_PORT override port: 18086
- UMS_CORS_ALLOWED_ORIGINS override accepted origin: https://admin.example.com
- UMS_CORS_ALLOWED_ORIGINS override excluded origin: none
- auth capabilities with config-only override: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
- auth capabilities with env override: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
## Evidence Files
- config-only.stdout.log
- config-only.stderr.log
- env-override.stdout.log
- env-override.stderr.log
- capabilities.config-only.json
- capabilities.env-override.json
- config.isolated.yaml

View File

@@ -0,0 +1,10 @@
{
"password": true,
"email_code": false,
"sms_code": false,
"password_reset": false,
"oauth_providers": [
]
}

View File

@@ -0,0 +1,10 @@
{
"password": true,
"email_code": false,
"sms_code": false,
"password_reset": false,
"oauth_providers": [
]
}

View File

@@ -0,0 +1,215 @@
server:
port: 18085
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # current runtime support: sqlite
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/config-isolation/20260324-103758/user_management.isolated.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: ""
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: ""
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: ""
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7澶?= 168灏忔椂
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "http://127.0.0.1:3000"
allowed_methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- X-Requested-With
- X-CSRF-Token
max_age: 3600
email:
host: "" # 鐢熶骇鐜濉啓鐪熷疄 SMTP Host
port: 18085
username: ""
password: ""
from_email: ""
from_name: "鐢ㄦ埛绠$悊绯荤粺"
sms:
enabled: false
provider: "" # aliyun, tencent锛涚暀绌鸿〃绀虹鐢ㄧ煭淇¤兘鍔? code_ttl: 5m
resend_cooldown: 1m
max_daily_limit: 10
aliyun:
access_key_id: ""
access_key_secret: ""
sign_name: ""
template_code: ""
endpoint: ""
region_id: "cn-hangzhou"
code_param_name: "code"
tencent:
secret_id: ""
secret_key: ""
app_id: ""
sign_name: ""
template_id: ""
region: "ap-guangzhou"
endpoint: ""
password_reset:
token_ttl: 15m
site_url: "http://localhost:8080"
# OAuth 绀句氦鐧诲綍閰嶇疆锛堢暀绌哄垯绂佺敤瀵瑰簲 Provider锛?
oauth:
google:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/google/callback"
wechat:
app_id: ""
app_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/wechat/callback"
github:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/github/callback"
qq:
app_id: ""
app_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/qq/callback"
alipay:
app_id: ""
private_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/alipay/callback"
sandbox: false
douyin:
client_key: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/douyin/callback"
# Webhook 鍏ㄥ眬閰嶇疆
webhook:
enabled: true
secret_header: "X-Webhook-Signature" # 绛惧悕 Header 鍚嶇О
timeout_sec: 30 # 鍗曟鎶曢€掕秴鏃讹紙绉掞級
max_retries: 3 # 鏈€澶ч噸璇曟鏁?
retry_backoff: "exponential" # 閫€閬跨瓥鐣ワ細exponential / fixed
worker_count: 4 # 鍚庡彴鎶曢€掑崗绋嬫暟
queue_size: 1000 # 鎶曢€掗槦鍒楀ぇ灏?
# IP 瀹夊叏閰嶇疆
ip_security:
auto_block_enabled: true # 鏄惁鍚敤鑷姩灏佺
auto_block_duration: 30m # 鑷姩灏佺鏃堕暱
brute_force_threshold: 10 # 鏆村姏鐮磋В闃堝€硷紙绐楀彛鍐呭け璐ユ鏁帮級
detection_window: 15m # 妫€娴嬫椂闂寸獥鍙?

View File

@@ -0,0 +1,113 @@
# Agent Browser Validation
- Date: 2026-03-24
- Tool: `agent-browser 0.22.0`
- Scope: verify whether newly installed `agent-browser` can extend current `frontend/admin` E2E closure beyond the existing Playwright CDP path
## Validation Goal
Determine whether `agent-browser` can:
- act as a stable browser automation path in the current constrained Windows environment
- close any remaining OS-level validation gap
- be promoted to a supported project E2E entrypoint
## Environment Findings
- PowerShell wrapper entrypoint `agent-browser.ps1` is blocked by execution policy in the current environment.
- The native binary is callable directly:
- `C:\Users\Admin\AppData\Roaming\npm\node_modules\agent-browser\bin\agent-browser-win32-x64.exe`
- `agent-browser` requires its daemon socket directory to be redirected to a writable root:
- `AGENT_BROWSER_SOCKET_DIR=C:\Users\Admin\.codex\memories\agent-browser-home\socket`
- Official browser bootstrap path was also tested:
- `agent-browser install`
- result: failed to fetch Chrome for Testing version metadata from `googlechromelabs.github.io`
- conclusion: the official first-run install path is not currently closed in this environment
## Execution Paths Tested
### 1. Native launch mode
Tested with:
- `--executable-path C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe`
- `--executable-path C:\Users\Admin\AppData\Local\ms-playwright\chromium-1208\chrome-win64\chrome.exe`
- crash-dialog / crashpad suppression args aligned with the existing stable browser wrapper:
- `--noerrdialogs`
- `--disable-breakpad`
- `--disable-crash-reporter`
- `--disable-crashpad-for-testing`
- `--no-sandbox`
- `--disable-dev-shm-usage`
- `--headless=new`
Result:
- failed before DevTools became ready
- representative error:
- `Chrome exited early ... without writing DevToolsActivePort`
- crashpad / mojo access-denied errors were still present
- the failure reproduced both with system Edge and with Playwright cached Chromium `chrome.exe`
Conclusion:
- `agent-browser` launch mode is not currently usable as a stable browser launcher in this environment
### 2. External CDP connect mode
Tested by connecting `agent-browser` to the already stabilized external browser path started by [`frontend/admin/scripts/run-cdp-smoke.ps1`](/D:/project/frontend/admin/scripts/run-cdp-smoke.ps1).
Result:
- stable for observation steps:
- `open`
- `wait --load networkidle`
- `snapshot -i`
- `get text`
- successful snapshot captured interactive refs on `/login`, including:
- username textbox `@e7`
- password textbox `@e8`
- login button `@e6`
- partially usable for limited in-page actions:
- `focus @e7`: succeeded
- `eval` against the page context: succeeded for DOM value injection
- not stable for user-like interaction steps:
- `fill` timed out repeatedly after successful snapshot
- `type @e7 e2e_admin`: failed with read timeout / host not responding
- `keyboard inserttext e2e_admin`: failed with `CDP error (Input.dispatchKeyEvent): Invalid 'text' parameter`
- `click @e6` after successful `eval`-based field population: failed with read timeout / host not responding
- `eval`-triggered DOM `submit.click()` returned successfully, but the subsequent `wait --url **/dashboard` still failed with read timeout / host not responding
Representative result:
- `open http://127.0.0.1:3000/login`: success
- `snapshot -i`: success
- `get text @e2`: success
- `focus @e7`: success
- `eval` to set username: success
- `fill @e7 e2e_admin`: failed with read timeout / host not responding
- `type @e7 e2e_admin`: failed with read timeout / host not responding
- `keyboard inserttext e2e_admin`: failed with invalid CDP parameter
- `click @e6`: failed with read timeout / host not responding
- DOM-triggered login + `wait --url **/dashboard`: failed with read timeout / host not responding
Conclusion:
- in the current environment, `agent-browser` connect mode is usable for observational inspection and limited in-page diagnostics
- it is not reliable for user-like interactive E2E execution or workflow progression
## Real Conclusion
- Installing `agent-browser` does not currently close the remaining OS-level validation gap.
- It does not replace the existing supported E2E path.
- Current supported browser-level E2E path remains:
- Playwright library
- external browser launch
- CDP connection
- [`npm.cmd run e2e:full:win`](/D:/project/frontend/admin/package.json)
- `agent-browser` is currently best described as:
- installed
- partially usable for read-only browser inspection plus limited DOM-assisted diagnostics
- not yet a supported interactive E2E runner
- not evidence of full OS-level automation closure
- not capable of supporting full simulated user-operation or OS-level validation in the current environment

View File

@@ -0,0 +1,57 @@
# Playwright CDP E2E Closure
- Date: 2026-03-24
- Scope: `frontend/admin` full real-browser E2E through external browser launch + Playwright CDP connection
- Environment: Windows PowerShell, current constrained environment where `playwright test` worker spawn is blocked by `spawn EPERM`
## Commands Executed
```powershell
cd D:\project\frontend\admin
npm.cmd run lint
npm.cmd run build
npm.cmd run test:run
npm.cmd run e2e:full:win
1..3 | ForEach-Object { npm.cmd run e2e:full:win }
```
## Validated Results
- `npm.cmd run lint`: passed
- `npm.cmd run build`: passed
- `npm.cmd run test:run`: passed
- test files: `7`
- tests: `24`
- `npm.cmd run e2e:full:win`: passed
- After browser cleanup hardening in [`frontend/admin/scripts/run-cdp-smoke.ps1`](/D:/project/frontend/admin/scripts/run-cdp-smoke.ps1), three consecutive reruns of `npm.cmd run e2e:full:win` all passed without wrapper retry
## Full E2E Scenarios
- `login-surface`
- `auth-workflow`
- `responsive-login`
- `desktop-mobile-navigation`
## Failure Signals Enforced
The Playwright CDP harness treats the following as failures:
- console errors
- native dialogs
- popup pages
- page errors
- request failures
- `401` responses
- blocked `window` guard events
No such failure signal was observed in the successful runs above.
## Closure Notes
- Current supported E2E path is browser-level real validation, not DOM mock.
- Current supported E2E path is `Playwright library + external browser + CDP`; it does not depend on `playwright test` runner workers.
- This is not full OS-level automation. It does not claim coverage for native file pickers, system permission dialogs, or other desktop-level interactions.
## Conclusion
In the current constrained Windows environment, the browser-level E2E closure for `frontend/admin` is complete and reproducibly passing on the supported CDP path.

View File

@@ -0,0 +1,57 @@
# Raw CDP Windows Stability Evidence
- Generated at: 2026-03-24 12:18:16 +08:00
- Scope: `frontend/admin` raw CDP Windows smoke stability after `chrome-headless-shell` crash-dialog and residual-process mitigation
## Commands Executed
```powershell
cd D:\project\frontend\admin
npm.cmd run e2e:auth-smoke:win
npm.cmd run e2e:smoke:win
```
## Auth Smoke Result
- Command exit: `0`
- `chrome-headless-shell` count before run: `76`
- `chrome-headless-shell` count after run: `76`
- Key output:
- `login landing path: /users`
- `user detail title: 用户详情`
- `assign roles title: 分配角色 - e2e_admin`
- `roles path: /roles`
- `permissions title: 分配权限 - 管理员`
- `dashboard path: /dashboard`
- `logout path: /login`
- `login-initial: 105ms`
- `login-desktop: 194ms`
- `login-tablet: 100ms`
- `login-mobile: 90ms`
## Smoke Result
- Command exit: `0`
- `chrome-headless-shell` count before run: `76`
- `chrome-headless-shell` count after run: `76`
- Key output:
- `protected dashboard redirect: /login (from=/dashboard)`
- `protected users redirect: /login (from=/users)`
- `login-initial: 89ms`
- `login-desktop: 185ms`
- `login-tablet: 119ms`
- `login-mobile: 88ms`
## Mitigation Applied
- `frontend/admin/scripts/run-cdp-smoke.ps1`
- added `--noerrdialogs`
- added `--disable-breakpad`
- added `--disable-crash-reporter`
- added `--disable-crashpad-for-testing`
## Conclusion
- Raw CDP Windows `smoke` and `auth smoke` both exited successfully after mitigation.
- Current local `chrome-headless-shell` process count did not increase across either run.
- This closes the previously observed “business flow passes but command exits non-zero because of new leaked PID” gap for the current environment.

View File

@@ -0,0 +1,26 @@
# Local Observability Baseline
- Generated at: 2026-03-24 08:43:35 +08:00
- Scope: single-node local baseline, not a production traffic certification result
## Concurrent Login Baseline
- Source command: `go test ./internal/e2e -run TestE2EConcurrentLogin -v -count=1`
- Concurrency configured by test: 20
- Result: success=2 fail=18 status=map[] total= avg=
- Interpretation: current login rate limiter absorbs most burst traffic with 429, while successful requests remained sub-second and no 5xx appeared.
## Browser Flow Baseline
- Source command: `cd frontend/admin && npm.cmd run e2e:auth-smoke:win`
- login-initial: 66ms
- login-desktop: 188ms
- login-tablet: 65ms
- login-mobile: 67ms
- Interpretation: current raw CDP browser validation stayed well below the existing `HighResponseTime` alert threshold of 1s in `deployment/alertmanager/alerts.yml`.
## Evidence Files
- concurrent-login-20260324-084309.txt
- raw-cdp-auth-smoke-20260324-084309.txt

View File

@@ -0,0 +1,26 @@
# Local Observability Baseline
- Generated at: 2026-03-24 08:44:26 +08:00
- Scope: single-node local baseline, not a production traffic certification result
## Concurrent Login Baseline
- Source command: `go test ./internal/e2e -run TestE2EConcurrentLogin -v -count=1`
- Concurrency configured by test: 20
- Result: success=2 fail=18 status=map[200:2 429:18] total=105.944ms avg=12.496245ms
- Interpretation: current login rate limiter absorbs most burst traffic with 429, while successful requests remained sub-second and no 5xx appeared.
## Browser Flow Baseline
- Source command: `cd frontend/admin && npm.cmd run e2e:auth-smoke:win`
- login-initial: 65ms
- login-desktop: 160ms
- login-tablet: 63ms
- login-mobile: 66ms
- Interpretation: current raw CDP browser validation stayed well below the existing `HighResponseTime` alert threshold of 1s in `deployment/alertmanager/alerts.yml`.
## Evidence Files
- concurrent-login-20260324-084358.txt
- raw-cdp-auth-smoke-20260324-084358.txt

View File

@@ -0,0 +1,26 @@
# Local Observability Baseline
- Generated at: 2026-03-24 09:01:55 +08:00
- Scope: single-node local baseline, not a production traffic certification result
## Concurrent Login Baseline
- Source command: `go test ./internal/e2e -run TestE2EConcurrentLogin -v -count=1`
- Concurrency configured by test: 20
- Result: success=2 fail=18 status=map[200:2 429:18] total=99.6704ms avg=13.38931ms
- Interpretation: current login rate limiter absorbs most burst traffic with 429, while successful requests remained sub-second and no 5xx appeared.
## Browser Flow Baseline
- Source command: `cd frontend/admin && npm.cmd run e2e:auth-smoke:win`
- login-initial: 91ms
- login-desktop: 174ms
- login-tablet: 107ms
- login-mobile: 102ms
- Interpretation: current raw CDP browser validation stayed well below the existing `HighResponseTime` alert threshold of 1s in `deployment/alertmanager/alerts.yml`.
## Evidence Files
- concurrent-login-20260324-090126.txt
- raw-cdp-auth-smoke-20260324-090126.txt

View File

@@ -0,0 +1,26 @@
# Local Observability Baseline
- Generated at: 2026-03-24 09:07:04 +08:00
- Scope: single-node local baseline, not a production traffic certification result
## Concurrent Login Baseline
- Source command: `go test ./internal/e2e -run TestE2EConcurrentLogin -v -count=1`
- Concurrency configured by test: 20
- Result: success=2 fail=18 status=map[200:2 429:18] total=109.0339ms avg=12.76726ms
- Interpretation: current login rate limiter absorbs most burst traffic with 429, while successful requests remained sub-second and no 5xx appeared.
## Browser Flow Baseline
- Source command: `cd frontend/admin && npm.cmd run e2e:auth-smoke:win`
- login-initial: 98ms
- login-desktop: 242ms
- login-tablet: 100ms
- login-mobile: 90ms
- Interpretation: current raw CDP browser validation stayed well below the existing `HighResponseTime` alert threshold of 1s in `deployment/alertmanager/alerts.yml`.
## Evidence Files
- concurrent-login-20260324-090637.txt
- raw-cdp-auth-smoke-20260324-090637.txt

View File

@@ -0,0 +1,27 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 07:26:04 POST /api/v1/auth/register | status: 200 | latency: 103.9129ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 429 | latency: 1.0604ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 200 | latency: 94.4768ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 07:26:04 POST /api/v1/auth/login | status: 200 | latency: 95.4917ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=97.5545ms 平均=11.95741ms
--- PASS: TestE2EConcurrentLogin (0.21s)
PASS
ok github.com/user-management-system/internal/e2e 0.420s

View File

@@ -0,0 +1,26 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 08:21:16 POST /api/v1/auth/register | status: 200 | latency: 111.6755ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 200 | latency: 97.2042ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:21:16 POST /api/v1/auth/login | status: 200 | latency: 98.8483ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=99.9078ms 平均=12.289135ms
--- PASS: TestE2EConcurrentLogin (0.22s)
PASS
ok github.com/user-management-system/internal/e2e 0.433s

View File

@@ -0,0 +1,26 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 08:40:32 POST /api/v1/auth/register | status: 200 | latency: 127.2361ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 1.0313ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 200 | latency: 114.742ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:40:32 POST /api/v1/auth/login | status: 200 | latency: 114.6852ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=116.7124ms 平均=13.86803ms
--- PASS: TestE2EConcurrentLogin (0.26s)
PASS
ok github.com/user-management-system/internal/e2e 0.553s

View File

@@ -0,0 +1,26 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 08:41:18 POST /api/v1/auth/register | status: 200 | latency: 112.4526ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 1.0393ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:18 POST /api/v1/auth/login | status: 200 | latency: 94.2175ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:41:19 POST /api/v1/auth/login | status: 200 | latency: 118.4367ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=120.1013ms 平均=13.32342ms
--- PASS: TestE2EConcurrentLogin (0.24s)
PASS
ok github.com/user-management-system/internal/e2e 0.563s

View File

@@ -0,0 +1,26 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 08:42:06 POST /api/v1/auth/register | status: 200 | latency: 110.3419ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 1.0561ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 21µs | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 885.3µs | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 62.8µs | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 62.8µs | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:06 POST /api/v1/auth/login | status: 200 | latency: 95.3272ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:42:07 POST /api/v1/auth/login | status: 200 | latency: 106.7957ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=108.6628ms 平均=12.345895ms
--- PASS: TestE2EConcurrentLogin (0.23s)
PASS
ok github.com/user-management-system/internal/e2e 0.532s

View File

@@ -0,0 +1,26 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 08:43:12 POST /api/v1/auth/register | status: 200 | latency: 138.712ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 1.0708ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 1.0708ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 1.0306ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 1.0306ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 200 | latency: 105.8988ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:43:12 POST /api/v1/auth/login | status: 200 | latency: 119.3284ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=122.5122ms 平均=13.78074ms
--- PASS: TestE2EConcurrentLogin (0.28s)
PASS
ok github.com/user-management-system/internal/e2e 0.525s

View File

@@ -0,0 +1,26 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 08:44:01 POST /api/v1/auth/register | status: 200 | latency: 126.1343ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 1.0305ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 1.0305ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 200 | latency: 102.41ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 08:44:01 POST /api/v1/auth/login | status: 200 | latency: 103.9633ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=105.944ms 平均=12.496245ms
--- PASS: TestE2EConcurrentLogin (0.24s)
PASS
ok github.com/user-management-system/internal/e2e 0.550s

View File

@@ -0,0 +1,26 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 09:01:29 POST /api/v1/auth/register | status: 200 | latency: 110.7768ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 1.0327ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 1.0327ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 1.0409ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 200 | latency: 96.0334ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:01:29 POST /api/v1/auth/login | status: 200 | latency: 98.6204ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=99.6704ms 平均=13.38931ms
--- PASS: TestE2EConcurrentLogin (0.23s)
PASS
ok github.com/user-management-system/internal/e2e 0.514s

View File

@@ -0,0 +1,26 @@
=== RUN TestE2EConcurrentLogin
[API] 2026-03-24 09:06:41 POST /api/v1/auth/register | status: 200 | latency: 123.7618ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 429 | latency: 0s | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 200 | latency: 96.6395ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
[API] 2026-03-24 09:06:41 POST /api/v1/auth/login | status: 200 | latency: 108.4945ms | ip: 127.0.0.1 | user_id: <nil> | ua: Go-http-client/1.1
e2e_test.go:397: 并发登录结果: 成功=2 失败=18 状态码分布=map[200:2 429:18] 总耗时=109.0339ms 平均=12.76726ms
--- PASS: TestE2EConcurrentLogin (0.25s)
PASS
ok github.com/user-management-system/internal/e2e 0.626s

View File

@@ -0,0 +1,31 @@
> admin@0.0.0 e2e:auth-smoke:win
> powershell -ExecutionPolicy Bypass -File ./scripts/run-cdp-auth-smoke.ps1
CDP smoke completed successfully
browser: HeadlessChrome/145.0.7632.6
title: 用户管理系统
capabilities: password=true email=false sms=false passwordReset=false
tabs:
forgot-password path: disabled
protected dashboard redirect: /login (from=/dashboard)
protected users redirect: /login (from=/users)
pre-login users redirect from: /users
login landing path: /users
user detail title: 用户详情
assign roles title: 分配角色 - e2e_admin
roles path: /roles
permissions title: 分配权限 - 管理员
dashboard path: /dashboard
logout path: /login
post-logout dashboard redirect: /login (from=/dashboard)
post-logout users redirect: /login (from=/users)
responsive:
- desktop: innerWidth=1920, bodyScrollWidth=1920
- tablet: innerWidth=768, bodyScrollWidth=768
- mobile: innerWidth=375, bodyScrollWidth=375
load timings:
- login-initial: 66ms
- login-desktop: 176ms
- login-tablet: 65ms
- login-mobile: 69ms

View File

@@ -0,0 +1 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.

View File

@@ -0,0 +1,31 @@
> admin@0.0.0 e2e:auth-smoke:win
> powershell -ExecutionPolicy Bypass -File ./scripts/run-cdp-auth-smoke.ps1
CDP smoke completed successfully
browser: HeadlessChrome/145.0.7632.6
title: 用户管理系统
capabilities: password=true email=false sms=false passwordReset=false
tabs:
forgot-password path: disabled
protected dashboard redirect: /login (from=/dashboard)
protected users redirect: /login (from=/users)
pre-login users redirect from: /users
login landing path: /users
user detail title: 用户详情
assign roles title: 分配角色 - e2e_admin
roles path: /roles
permissions title: 分配权限 - 管理员
dashboard path: /dashboard
logout path: /login
post-logout dashboard redirect: /login (from=/dashboard)
post-logout users redirect: /login (from=/users)
responsive:
- desktop: innerWidth=1920, bodyScrollWidth=1920
- tablet: innerWidth=768, bodyScrollWidth=768
- mobile: innerWidth=375, bodyScrollWidth=375
load timings:
- login-initial: 74ms
- login-desktop: 191ms
- login-tablet: 67ms
- login-mobile: 74ms

View File

@@ -0,0 +1,8 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.
browser cleanup leaked PIDs: 42132
ËùÔÚλÖà D:\project\frontend\admin\scripts\run-cdp-smoke.ps1:204 ×Ö·û: 5
+ throw "browser cleanup leaked PIDs: $($newIds -join ', ')"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (browser cleanup leaked PIDs: 42132:String) [], RuntimeException
+ FullyQualifiedErrorId : browser cleanup leaked PIDs: 42132

View File

@@ -0,0 +1,31 @@
> admin@0.0.0 e2e:auth-smoke:win
> powershell -ExecutionPolicy Bypass -File ./scripts/run-cdp-auth-smoke.ps1
CDP smoke completed successfully
browser: HeadlessChrome/145.0.7632.6
title: 用户管理系统
capabilities: password=true email=false sms=false passwordReset=false
tabs:
forgot-password path: disabled
protected dashboard redirect: /login (from=/dashboard)
protected users redirect: /login (from=/users)
pre-login users redirect from: /users
login landing path: /users
user detail title: 用户详情
assign roles title: 分配角色 - e2e_admin
roles path: /roles
permissions title: 分配权限 - 管理员
dashboard path: /dashboard
logout path: /login
post-logout dashboard redirect: /login (from=/dashboard)
post-logout users redirect: /login (from=/users)
responsive:
- desktop: innerWidth=1920, bodyScrollWidth=1920
- tablet: innerWidth=768, bodyScrollWidth=768
- mobile: innerWidth=375, bodyScrollWidth=375
load timings:
- login-initial: 69ms
- login-desktop: 182ms
- login-tablet: 67ms
- login-mobile: 65ms

View File

@@ -0,0 +1 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.

View File

@@ -0,0 +1,31 @@
> admin@0.0.0 e2e:auth-smoke:win
> powershell -ExecutionPolicy Bypass -File ./scripts/run-cdp-auth-smoke.ps1
CDP smoke completed successfully
browser: HeadlessChrome/145.0.7632.6
title: 用户管理系统
capabilities: password=true email=false sms=false passwordReset=false
tabs:
forgot-password path: disabled
protected dashboard redirect: /login (from=/dashboard)
protected users redirect: /login (from=/users)
pre-login users redirect from: /users
login landing path: /users
user detail title: 用户详情
assign roles title: 分配角色 - e2e_admin
roles path: /roles
permissions title: 分配权限 - 管理员
dashboard path: /dashboard
logout path: /login
post-logout dashboard redirect: /login (from=/dashboard)
post-logout users redirect: /login (from=/users)
responsive:
- desktop: innerWidth=1920, bodyScrollWidth=1920
- tablet: innerWidth=768, bodyScrollWidth=768
- mobile: innerWidth=375, bodyScrollWidth=375
load timings:
- login-initial: 74ms
- login-desktop: 185ms
- login-tablet: 74ms
- login-mobile: 70ms

View File

@@ -0,0 +1,8 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.
browser cleanup leaked PIDs: 19372
ËùÔÚλÖà D:\project\frontend\admin\scripts\run-cdp-smoke.ps1:204 ×Ö·û: 5
+ throw "browser cleanup leaked PIDs: $($newIds -join ', ')"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (browser cleanup leaked PIDs: 19372:String) [], RuntimeException
+ FullyQualifiedErrorId : browser cleanup leaked PIDs: 19372

View File

@@ -0,0 +1,31 @@
> admin@0.0.0 e2e:auth-smoke:win
> powershell -ExecutionPolicy Bypass -File ./scripts/run-cdp-auth-smoke.ps1
CDP smoke completed successfully
browser: HeadlessChrome/145.0.7632.6
title: 用户管理系统
capabilities: password=true email=false sms=false passwordReset=false
tabs:
forgot-password path: disabled
protected dashboard redirect: /login (from=/dashboard)
protected users redirect: /login (from=/users)
pre-login users redirect from: /users
login landing path: /users
user detail title: 用户详情
assign roles title: 分配角色 - e2e_admin
roles path: /roles
permissions title: 分配权限 - 管理员
dashboard path: /dashboard
logout path: /login
post-logout dashboard redirect: /login (from=/dashboard)
post-logout users redirect: /login (from=/users)
responsive:
- desktop: innerWidth=1920, bodyScrollWidth=1920
- tablet: innerWidth=768, bodyScrollWidth=768
- mobile: innerWidth=375, bodyScrollWidth=375
load timings:
- login-initial: 66ms
- login-desktop: 188ms
- login-tablet: 65ms
- login-mobile: 67ms

View File

@@ -0,0 +1 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.

View File

@@ -0,0 +1,31 @@
> admin@0.0.0 e2e:auth-smoke:win
> powershell -ExecutionPolicy Bypass -File ./scripts/run-cdp-auth-smoke.ps1
CDP smoke completed successfully
browser: HeadlessChrome/145.0.7632.6
title: 用户管理系统
capabilities: password=true email=false sms=false passwordReset=false
tabs:
forgot-password path: disabled
protected dashboard redirect: /login (from=/dashboard)
protected users redirect: /login (from=/users)
pre-login users redirect from: /users
login landing path: /users
user detail title: 用户详情
assign roles title: 分配角色 - e2e_admin
roles path: /roles
permissions title: 分配权限 - 管理员
dashboard path: /dashboard
logout path: /login
post-logout dashboard redirect: /login (from=/dashboard)
post-logout users redirect: /login (from=/users)
responsive:
- desktop: innerWidth=1920, bodyScrollWidth=1920
- tablet: innerWidth=768, bodyScrollWidth=768
- mobile: innerWidth=375, bodyScrollWidth=375
load timings:
- login-initial: 65ms
- login-desktop: 160ms
- login-tablet: 63ms
- login-mobile: 66ms

View File

@@ -0,0 +1,8 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.
browser cleanup leaked PIDs: 33064
ËùÔÚλÖà D:\project\frontend\admin\scripts\run-cdp-smoke.ps1:204 ×Ö·û: 5
+ throw "browser cleanup leaked PIDs: $($newIds -join ', ')"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (browser cleanup leaked PIDs: 33064:String) [], RuntimeException
+ FullyQualifiedErrorId : browser cleanup leaked PIDs: 33064

View File

@@ -0,0 +1,31 @@
> admin@0.0.0 e2e:auth-smoke:win
> powershell -ExecutionPolicy Bypass -File ./scripts/run-cdp-auth-smoke.ps1
CDP smoke completed successfully
browser: HeadlessChrome/145.0.7632.6
title: 用户管理系统
capabilities: password=true email=false sms=false passwordReset=false
tabs:
forgot-password path: disabled
protected dashboard redirect: /login (from=/dashboard)
protected users redirect: /login (from=/users)
pre-login users redirect from: /users
login landing path: /users
user detail title: 用户详情
assign roles title: 分配角色 - e2e_admin
roles path: /roles
permissions title: 分配权限 - 管理员
dashboard path: /dashboard
logout path: /login
post-logout dashboard redirect: /login (from=/dashboard)
post-logout users redirect: /login (from=/users)
responsive:
- desktop: innerWidth=1920, bodyScrollWidth=1920
- tablet: innerWidth=768, bodyScrollWidth=768
- mobile: innerWidth=375, bodyScrollWidth=375
load timings:
- login-initial: 91ms
- login-desktop: 174ms
- login-tablet: 107ms
- login-mobile: 102ms

View File

@@ -0,0 +1,8 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.
browser cleanup leaked PIDs: 47848
ËùÔÚλÖà D:\project\frontend\admin\scripts\run-cdp-smoke.ps1:199 ×Ö·û: 5
+ throw "browser cleanup leaked PIDs: $($newIds -join ', ')"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (browser cleanup leaked PIDs: 47848:String) [], RuntimeException
+ FullyQualifiedErrorId : browser cleanup leaked PIDs: 47848

View File

@@ -0,0 +1,31 @@
> admin@0.0.0 e2e:auth-smoke:win
> powershell -ExecutionPolicy Bypass -File ./scripts/run-cdp-auth-smoke.ps1
CDP smoke completed successfully
browser: HeadlessChrome/145.0.7632.6
title: 用户管理系统
capabilities: password=true email=false sms=false passwordReset=false
tabs:
forgot-password path: disabled
protected dashboard redirect: /login (from=/dashboard)
protected users redirect: /login (from=/users)
pre-login users redirect from: /users
login landing path: /users
user detail title: 用户详情
assign roles title: 分配角色 - e2e_admin
roles path: /roles
permissions title: 分配权限 - 管理员
dashboard path: /dashboard
logout path: /login
post-logout dashboard redirect: /login (from=/dashboard)
post-logout users redirect: /login (from=/users)
responsive:
- desktop: innerWidth=1920, bodyScrollWidth=1920
- tablet: innerWidth=768, bodyScrollWidth=768
- mobile: innerWidth=375, bodyScrollWidth=375
load timings:
- login-initial: 98ms
- login-desktop: 242ms
- login-tablet: 100ms
- login-mobile: 90ms

View File

@@ -0,0 +1 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.

View File

@@ -0,0 +1,32 @@
# Rollback Drill
- Generated at: 2026-03-24 08:49:39 +08:00
- Source DB: D:\project\data\user_management.db
- Stable DB copy: D:\project\docs\evidence\ops\2026-03-24\rollback\20260324-084928\user_management.stable.db
- Probe port: 18087
## Drill Result
- Stable release started successfully before rollback gate evaluation.
- Candidate release was rejected by release-mode runtime validation before becoming healthy.
- Rollback to the previous stable config/artifact path completed successfully on the same probe port.
- Candidate rejection evidence: stderr matched release validation failure
- Stable capabilities before rollback: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
- Stable capabilities after rollback: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
## Scope Note
- This local drill validates rollback operational steps and health gates for the current artifact/config path.
- It does not prove cross-version schema downgrade compatibility between distinct historical releases.
## Evidence Files
- config.stable.yaml
- config.candidate.yaml
- stable-initial.stdout.log
- stable-initial.stderr.log
- candidate.stdout.log
- candidate.stderr.log
- stable-rollback.stdout.log
- stable-rollback.stderr.log

View File

@@ -0,0 +1,121 @@
server:
port: 18087
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # sqlite, postgresql, mysql
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/rollback/20260324-084928/user_management.stable.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: password
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: password
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: your-secret-key-change-in-production
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7澶?= 168灏忔椂
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "*"

View File

@@ -0,0 +1,215 @@
server:
port: 18087
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # sqlite, postgresql, mysql
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/rollback/20260324-084928/user_management.stable.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: password
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: password
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: your-secret-key-change-in-production
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7澶?= 168灏忔椂
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "http://127.0.0.1:3000"
allowed_methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- X-Requested-With
- X-CSRF-Token
max_age: 3600
email:
host: "" # 鐢熶骇鐜濉啓鐪熷疄 SMTP Host
port: 18087
username: ""
password: ""
from_email: ""
from_name: "鐢ㄦ埛绠$悊绯荤粺"
sms:
enabled: false
provider: "" # aliyun, tencent锛涚暀绌鸿〃绀虹鐢ㄧ煭淇¤兘鍔? code_ttl: 5m
resend_cooldown: 1m
max_daily_limit: 10
aliyun:
access_key_id: ""
access_key_secret: ""
sign_name: ""
template_code: ""
endpoint: ""
region_id: "cn-hangzhou"
code_param_name: "code"
tencent:
secret_id: ""
secret_key: ""
app_id: ""
sign_name: ""
template_id: ""
region: "ap-guangzhou"
endpoint: ""
password_reset:
token_ttl: 15m
site_url: "http://localhost:8080"
# OAuth 绀句氦鐧诲綍閰嶇疆锛堢暀绌哄垯绂佺敤瀵瑰簲 Provider锛?
oauth:
google:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/google/callback"
wechat:
app_id: ""
app_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/wechat/callback"
github:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/github/callback"
qq:
app_id: ""
app_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/qq/callback"
alipay:
app_id: ""
private_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/alipay/callback"
sandbox: false
douyin:
client_key: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/douyin/callback"
# Webhook 鍏ㄥ眬閰嶇疆
webhook:
enabled: true
secret_header: "X-Webhook-Signature" # 绛惧悕 Header 鍚嶇О
timeout_sec: 30 # 鍗曟鎶曢€掕秴鏃讹紙绉掞級
max_retries: 3 # 鏈€澶ч噸璇曟鏁?
retry_backoff: "exponential" # 閫€閬跨瓥鐣ワ細exponential / fixed
worker_count: 4 # 鍚庡彴鎶曢€掑崗绋嬫暟
queue_size: 1000 # 鎶曢€掗槦鍒楀ぇ灏?
# IP 瀹夊叏閰嶇疆
ip_security:
auto_block_enabled: true # 鏄惁鍚敤鑷姩灏佺
auto_block_duration: 30m # 鑷姩灏佺鏃堕暱
brute_force_threshold: 10 # 鏆村姏鐮磋В闃堝€硷紙绐楀彛鍐呭け璐ユ鏁帮級
detection_window: 15m # 妫€娴嬫椂闂寸獥鍙?

View File

@@ -0,0 +1,32 @@
# Rollback Drill
- Generated at: 2026-03-24 10:38:12 +08:00
- Source DB: D:\project\data\user_management.db
- Stable DB copy: D:\project\docs\evidence\ops\2026-03-24\rollback\20260324-103758\user_management.stable.db
- Probe port: 18087
## Drill Result
- Stable release started successfully before rollback gate evaluation.
- Candidate release was rejected by release-mode runtime validation before becoming healthy.
- Rollback to the previous stable config/artifact path completed successfully on the same probe port.
- Candidate rejection evidence: stderr matched release validation failure
- Stable capabilities before rollback: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
- Stable capabilities after rollback: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
## Scope Note
- This local drill validates rollback operational steps and health gates for the current artifact/config path.
- It does not prove cross-version schema downgrade compatibility between distinct historical releases.
## Evidence Files
- config.stable.yaml
- config.candidate.yaml
- stable-initial.stdout.log
- stable-initial.stderr.log
- candidate.stdout.log
- candidate.stderr.log
- stable-rollback.stdout.log
- stable-rollback.stderr.log

View File

@@ -0,0 +1,121 @@
server:
port: 18087
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # current runtime support: sqlite
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/rollback/20260324-103758/user_management.stable.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: ""
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: ""
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: ""
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7澶?= 168灏忔椂
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "*"

View File

@@ -0,0 +1,215 @@
server:
port: 18087
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # current runtime support: sqlite
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/rollback/20260324-103758/user_management.stable.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: ""
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: ""
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: ""
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7澶?= 168灏忔椂
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "http://127.0.0.1:3000"
allowed_methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- X-Requested-With
- X-CSRF-Token
max_age: 3600
email:
host: "" # 鐢熶骇鐜濉啓鐪熷疄 SMTP Host
port: 18087
username: ""
password: ""
from_email: ""
from_name: "鐢ㄦ埛绠$悊绯荤粺"
sms:
enabled: false
provider: "" # aliyun, tencent锛涚暀绌鸿〃绀虹鐢ㄧ煭淇¤兘鍔? code_ttl: 5m
resend_cooldown: 1m
max_daily_limit: 10
aliyun:
access_key_id: ""
access_key_secret: ""
sign_name: ""
template_code: ""
endpoint: ""
region_id: "cn-hangzhou"
code_param_name: "code"
tencent:
secret_id: ""
secret_key: ""
app_id: ""
sign_name: ""
template_id: ""
region: "ap-guangzhou"
endpoint: ""
password_reset:
token_ttl: 15m
site_url: "http://localhost:8080"
# OAuth 绀句氦鐧诲綍閰嶇疆锛堢暀绌哄垯绂佺敤瀵瑰簲 Provider锛?
oauth:
google:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/google/callback"
wechat:
app_id: ""
app_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/wechat/callback"
github:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/github/callback"
qq:
app_id: ""
app_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/qq/callback"
alipay:
app_id: ""
private_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/alipay/callback"
sandbox: false
douyin:
client_key: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/douyin/callback"
# Webhook 鍏ㄥ眬閰嶇疆
webhook:
enabled: true
secret_header: "X-Webhook-Signature" # 绛惧悕 Header 鍚嶇О
timeout_sec: 30 # 鍗曟鎶曢€掕秴鏃讹紙绉掞級
max_retries: 3 # 鏈€澶ч噸璇曟鏁?
retry_backoff: "exponential" # 閫€閬跨瓥鐣ワ細exponential / fixed
worker_count: 4 # 鍚庡彴鎶曢€掑崗绋嬫暟
queue_size: 1000 # 鎶曢€掗槦鍒楀ぇ灏?
# IP 瀹夊叏閰嶇疆
ip_security:
auto_block_enabled: true # 鏄惁鍚敤鑷姩灏佺
auto_block_duration: 30m # 鑷姩灏佺鏃堕暱
brute_force_threshold: 10 # 鏆村姏鐮磋В闃堝€硷紙绐楀彛鍐呭け璐ユ鏁帮級
detection_window: 15m # 妫€娴嬫椂闂寸獥鍙?

View File

@@ -0,0 +1,32 @@
# SCA Summary
- Generated at: 2026-03-24 07:18:02 +08:00
- Project root: $projectRoot
## Commands
- cd frontend/admin && npm.cmd audit --omit=dev --json
- cd frontend/admin && npm.cmd audit --json
- go run golang.org/x/vuln/cmd/govulncheck@latest -json ./...
## Exit Codes
- npm audit production: 1
- npm audit full: 1
- govulncheck: 0
## Findings
- npm audit production: unavailable
- npm audit full: unavailable
- govulncheck findings: 4
## Evidence Files
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\sca\npm-audit-prod-20260324-071730.json -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\sca\npm-audit-prod-20260324-071730.stderr.txt -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\sca\npm-audit-full-20260324-071730.json -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\sca\npm-audit-full-20260324-071730.stderr.txt -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\sca\govulncheck-20260324-071730.jsonl -Leaf)
- $(Split-Path D:\project\docs\evidence\ops\2026-03-24\sca\govulncheck-20260324-071730.stderr.txt -Leaf)

View File

@@ -0,0 +1,33 @@
# SCA Summary
- Generated at: 2026-03-24 07:21:06 +08:00
- Project root: D:\project
## Commands
- `cd frontend/admin && npm.cmd audit --omit=dev --json --registry=https://registry.npmjs.org/`
- `cd frontend/admin && npm.cmd audit --json --registry=https://registry.npmjs.org/`
- `go run golang.org/x/vuln/cmd/govulncheck@latest -json ./...`
## Exit Codes
- npm audit production: 0
- npm audit full: 0
- govulncheck: 0
## Findings
- npm audit production: info=0 low=0 moderate=0 high=0 critical=0 total=0
- npm audit full: info=0 low=0 moderate=0 high=0 critical=0 total=0
- govulncheck reachable findings: 4
- govulncheck reachable IDs: GO-2025-3488, GO-2025-3553
## Evidence Files
- npm-audit-prod-20260324-072045.json
- npm-audit-prod-20260324-072045.stderr.txt
- npm-audit-full-20260324-072045.json
- npm-audit-full-20260324-072045.stderr.txt
- govulncheck-20260324-072045.jsonl
- govulncheck-20260324-072045.stderr.txt

View File

@@ -0,0 +1,33 @@
# SCA Summary
- Generated at: 2026-03-24 07:22:02 +08:00
- Project root: D:\project
## Commands
- `cd frontend/admin && npm.cmd audit --omit=dev --json --registry=https://registry.npmjs.org/`
- `cd frontend/admin && npm.cmd audit --json --registry=https://registry.npmjs.org/`
- `go run golang.org/x/vuln/cmd/govulncheck@latest -json ./...`
## Exit Codes
- npm audit production: 0
- npm audit full: 0
- govulncheck: 0
## Findings
- npm audit production: info=0 low=0 moderate=0 high=0 critical=0 total=0
- npm audit full: info=0 low=0 moderate=0 high=0 critical=0 total=0
- govulncheck reachable findings: 0
- govulncheck reachable IDs: none
## Evidence Files
- npm-audit-prod-20260324-072144.json
- npm-audit-prod-20260324-072144.stderr.txt
- npm-audit-full-20260324-072144.json
- npm-audit-full-20260324-072144.stderr.txt
- govulncheck-20260324-072144.jsonl
- govulncheck-20260324-072144.stderr.txt

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
go: downloading golang.org/x/vuln v1.1.4
go: downloading golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7
go: downloading golang.org/x/tools v0.29.0
go: downloading golang.org/x/mod v0.22.0
go: downloading golang.org/x/sync v0.10.0
go: downloading golang.org/x/sys v0.29.0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
{
"message": "404 Not Found - POST https://registry.npmmirror.com/-/npm/v1/security/advisories/bulk - [NOT_IMPLEMENTED] /-/npm/v1/security/* not implemented yet",
"method": "POST",
"uri": "https://registry.npmmirror.com/-/npm/v1/security/advisories/bulk",
"headers": {
"server": [
"Tengine"
],
"date": [
"Mon, 23 Mar 2026 23:17:33 GMT"
],
"content-type": [
"application/json"
],
"transfer-encoding": [
"chunked"
],
"connection": [
"keep-alive"
],
"strict-transport-security": [
"max-age=5184000"
],
"via": [
"kunlun13.cn7892[,404666]"
],
"timing-allow-origin": [
"*"
],
"eagleid": [
"b7f0ed2117743078539362653e"
],
"x-fetch-attempts": [
"1"
]
},
"statusCode": 404,
"body": {
"error": "[NOT_IMPLEMENTED] /-/npm/v1/security/* not implemented yet"
},
"error": {
"summary": "",
"detail": ""
}
}

View File

@@ -0,0 +1,5 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.
npm warn audit 404 Not Found - POST https://registry.npmmirror.com/-/npm/v1/security/advisories/bulk - [NOT_IMPLEMENTED] /-/npm/v1/security/* not implemented yet
npm error audit endpoint returned an error
npm error Log files were not written due to an error writing to the directory: C:\Users\Admin\AppData\Local\npm-cache\_logs
npm error You can rerun the command with `--loglevel=verbose` to see the logs in your terminal

View File

@@ -0,0 +1,22 @@
{
"auditReportVersion": 2,
"vulnerabilities": {},
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 0,
"high": 0,
"critical": 0,
"total": 0
},
"dependencies": {
"prod": 83,
"dev": 297,
"optional": 34,
"peer": 8,
"peerOptional": 0,
"total": 379
}
}
}

View File

@@ -0,0 +1 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.

View File

@@ -0,0 +1,22 @@
{
"auditReportVersion": 2,
"vulnerabilities": {},
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 0,
"high": 0,
"critical": 0,
"total": 0
},
"dependencies": {
"prod": 83,
"dev": 297,
"optional": 34,
"peer": 8,
"peerOptional": 0,
"total": 379
}
}
}

View File

@@ -0,0 +1 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.

View File

@@ -0,0 +1,45 @@
{
"message": "404 Not Found - POST https://registry.npmmirror.com/-/npm/v1/security/advisories/bulk - [NOT_IMPLEMENTED] /-/npm/v1/security/* not implemented yet",
"method": "POST",
"uri": "https://registry.npmmirror.com/-/npm/v1/security/advisories/bulk",
"headers": {
"server": [
"Tengine"
],
"date": [
"Mon, 23 Mar 2026 23:17:31 GMT"
],
"content-type": [
"application/json"
],
"transfer-encoding": [
"chunked"
],
"connection": [
"keep-alive"
],
"strict-transport-security": [
"max-age=5184000"
],
"via": [
"kunlun3.cn7892[,404666]"
],
"timing-allow-origin": [
"*"
],
"eagleid": [
"b7f0ed1717743078519287314e"
],
"x-fetch-attempts": [
"1"
]
},
"statusCode": 404,
"body": {
"error": "[NOT_IMPLEMENTED] /-/npm/v1/security/* not implemented yet"
},
"error": {
"summary": "",
"detail": ""
}
}

View File

@@ -0,0 +1,5 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.
npm warn audit 404 Not Found - POST https://registry.npmmirror.com/-/npm/v1/security/advisories/bulk - [NOT_IMPLEMENTED] /-/npm/v1/security/* not implemented yet
npm error audit endpoint returned an error
npm error Log files were not written due to an error writing to the directory: C:\Users\Admin\AppData\Local\npm-cache\_logs
npm error You can rerun the command with `--loglevel=verbose` to see the logs in your terminal

View File

@@ -0,0 +1,22 @@
{
"auditReportVersion": 2,
"vulnerabilities": {},
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 0,
"high": 0,
"critical": 0,
"total": 0
},
"dependencies": {
"prod": 83,
"dev": 297,
"optional": 34,
"peer": 8,
"peerOptional": 0,
"total": 379
}
}
}

View File

@@ -0,0 +1 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.

View File

@@ -0,0 +1,22 @@
{
"auditReportVersion": 2,
"vulnerabilities": {},
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 0,
"high": 0,
"critical": 0,
"total": 0
},
"dependencies": {
"prod": 83,
"dev": 297,
"optional": 34,
"peer": 8,
"peerOptional": 0,
"total": 379
}
}
}

View File

@@ -0,0 +1 @@
npm warn Unknown user config "//git@github.com/" (git config --global url."https://github.com/".insteadOf ssh://git@github.com/). This will stop working in the next major version of npm.

View File

@@ -0,0 +1,37 @@
# Secret Boundary Drill
- Generated at: 2026-03-24 10:41:28 +08:00
- Source DB: D:\project\data\user_management.db
- Isolated DB: D:\project\docs\evidence\ops\2026-03-24\secret-boundary\20260324-104122\user_management.secret-boundary.db
- Isolated config: D:\project\docs\evidence\ops\2026-03-24\secret-boundary\20260324-104122\config.secret-boundary.yaml
## Template Validation
- config template jwt.secret blank: True
- config template postgresql.password blank: True
- config template mysql.password blank: True
- forbidden placeholders removed from configs/config.yaml: True
- .gitignore protects local JWT key files: True
- .gitignore protects .env files: True
## Runtime Injection Validation
- Startup path: UMS_CONFIG_PATH + UMS_JWT_ALGORITHM + UMS_JWT_SECRET
- Synthetic JWT algorithm injected: HS256
- Synthetic JWT secret length: 45
- GET /health: pass
- GET /health/ready: pass
- GET /api/v1/auth/capabilities: {"password":true,"email_code":false,"sms_code":false,"password_reset":false,"oauth_providers":[]}
## Scope Note
- This drill proves the repo-level secret boundary and environment injection path are executable locally.
- It does not prove external secrets manager, KMS rotation, or CI/CD environment delivery evidence.
## Evidence Files
- server.stdout.log
- server.stderr.log
- capabilities.json
- config.secret-boundary.yaml

View File

@@ -0,0 +1,10 @@
{
"password": true,
"email_code": false,
"sms_code": false,
"password_reset": false,
"oauth_providers": [
]
}

View File

@@ -0,0 +1,216 @@
server:
port: 18088
mode: release # debug, release
read_timeout: 30s
read_header_timeout: 10s
write_timeout: 30s
idle_timeout: 60s
shutdown_timeout: 15s
max_header_bytes: 1048576
database:
type: sqlite # current runtime support: sqlite
sqlite:
path: "D:/project/docs/evidence/ops/2026-03-24/secret-boundary/20260324-104122/user_management.secret-boundary.db"
postgresql:
host: localhost
port: 5432
database: user_management
username: postgres
password: ""
ssl_mode: disable
max_open_conns: 100
max_idle_conns: 10
mysql:
host: localhost
port: 3306
database: user_management
username: root
password: ""
charset: utf8mb4
max_open_conns: 100
max_idle_conns: 10
cache:
l1:
enabled: true
max_size: 10000
ttl: 5m
l2:
enabled: false
type: redis
redis:
addr: localhost:6379
password: ""
db: 0
pool_size: 50
ttl: 30m
redis:
enabled: false
addr: localhost:6379
password: ""
db: 0
jwt:
algorithm: RS256
secret: ""
private_key_path: "./data/jwt/private.pem"
public_key_path: "./data/jwt/public.pem"
private_key_pem: ""
public_key_pem: ""
access_token_expire: 2h
refresh_token_expire: 168h # 7天 = 168小时
security:
password_min_length: 8
password_require_special: true
password_require_number: true
login_max_attempts: 5
login_lock_duration: 30m
ratelimit:
enabled: true
login:
enabled: true
algorithm: token_bucket
capacity: 5
rate: 1
window: 1m
register:
enabled: true
algorithm: leaky_bucket
capacity: 3
rate: 1
window: 1h
api:
enabled: true
algorithm: sliding_window
capacity: 1000
window: 1m
monitoring:
prometheus:
enabled: true
path: /metrics
tracing:
enabled: false
endpoint: http://localhost:4318
service_name: user-management-system
logging:
level: info # debug, info, warn, error
format: json # json, text
output:
- stdout
- ./logs/app.log
rotation:
max_size: 100 # MB
max_age: 30 # days
max_backups: 10
admin:
username: ""
password: ""
email: ""
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "http://127.0.0.1:3000"
allowed_methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- X-Requested-With
- X-CSRF-Token
max_age: 3600
email:
host: "" # 生产环境填写真实 SMTP Host
port: 18088
username: ""
password: ""
from_email: ""
from_name: "用户管理系统"
sms:
enabled: false
provider: "" # aliyun, tencent留空表示禁用短信能力
code_ttl: 5m
resend_cooldown: 1m
max_daily_limit: 10
aliyun:
access_key_id: ""
access_key_secret: ""
sign_name: ""
template_code: ""
endpoint: ""
region_id: "cn-hangzhou"
code_param_name: "code"
tencent:
secret_id: ""
secret_key: ""
app_id: ""
sign_name: ""
template_id: ""
region: "ap-guangzhou"
endpoint: ""
password_reset:
token_ttl: 15m
site_url: "http://localhost:8080"
# OAuth 社交登录配置(留空则禁用对应 Provider
oauth:
google:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/google/callback"
wechat:
app_id: ""
app_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/wechat/callback"
github:
client_id: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/github/callback"
qq:
app_id: ""
app_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/qq/callback"
alipay:
app_id: ""
private_key: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/alipay/callback"
sandbox: false
douyin:
client_key: ""
client_secret: ""
redirect_url: "http://localhost:8080/api/v1/auth/oauth/douyin/callback"
# Webhook 全局配置
webhook:
enabled: true
secret_header: "X-Webhook-Signature" # 签名 Header 名称
timeout_sec: 30 # 单次投递超时(秒)
max_retries: 3 # 最大重试次数
retry_backoff: "exponential" # 退避策略exponential / fixed
worker_count: 4 # 后台投递协程数
queue_size: 1000 # 投递队列大小
# IP 安全配置
ip_security:
auto_block_enabled: true # 是否启用自动封禁
auto_block_duration: 30m # 自动封禁时长
brute_force_threshold: 10 # 暴力破解阈值(窗口内失败次数)
detection_window: 15m # 检测时间窗口