Checkpoint: password reset, rule expiry, migrations

- Self-service and admin password-change endpoints
  (PUT /v1/auth/password, PUT /v1/accounts/{id}/password)
- Policy rule time-scoped expiry (not_before / expires_at)
  with migration 000006 and engine filtering
- golang-migrate integration; embedded SQL migrations
- PolicyRecord fieldalignment lint fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 14:38:38 -07:00
parent d7b69ed983
commit 22158824bd
25 changed files with 1574 additions and 137 deletions

View File

@@ -0,0 +1,47 @@
{{define "password_reset_form"}}
<form id="password-reset-form"
hx-put="/accounts/{{.Account.UUID}}/password"
hx-target="#password-reset-section"
hx-swap="innerHTML"
hx-headers='{"X-CSRF-Token": "{{.CSRFToken}}"}'
onsubmit="return mciasPwConfirm(this)">
<div class="form-group">
<label for="new_password">New Password</label>
<input type="password" id="new_password" name="new_password"
class="form-control" autocomplete="new-password"
placeholder="Minimum 12 characters" required minlength="12">
</div>
<div class="form-group" style="margin-top:.5rem">
<label for="confirm_password">Confirm Password</label>
<input type="password" id="confirm_password" name="confirm_password"
class="form-control" autocomplete="new-password"
placeholder="Repeat new password" required minlength="12">
</div>
<div id="pw-reset-error" role="alert"
style="display:none;color:var(--color-danger,#c0392b);font-size:.85rem;margin-top:.35rem"></div>
<button type="submit" class="btn btn-danger btn-sm" style="margin-top:.75rem">
Reset Password
</button>
</form>
<script>
function mciasPwConfirm(form) {
var pw = form.querySelector('#new_password').value;
var cfm = form.querySelector('#confirm_password').value;
var err = form.querySelector('#pw-reset-error');
if (pw !== cfm) {
err.textContent = 'Passwords do not match.';
err.style.display = 'block';
return false;
}
err.style.display = 'none';
return true;
}
</script>
{{end}}
{{define "password_reset_result"}}
{{if .Flash}}
<div class="alert alert-success" role="alert">{{.Flash}}</div>
{{end}}
{{template "password_reset_form" .}}
{{end}}