79a3358810
web/handlers/window.go: GET /window (list), GET /window/new (form),
POST /window (open), GET /window/{id} (detail+lifecycle+audit), POST
/window/{id}/activate|revoke|expire (lifecycle transitions). Store
extensions: OpenWindow/ActivateWindow/RevokeWindow/ExpireWindow/
ListWindows/GetWindow/GetAuditLog — all call the REAL x/window/types
Window.Activate/Revoke/Expire methods (not reimplementation). Revoke on
Expired is a no-op (v0.2 terminal-state contract). AuditEntry appended on
each transition. 3 Window templates. window_test.go: lifecycle
correctness (asserts real methods invoked), idempotent revoke, revoke-on-
expired no-op, G-026 error lexicon checks. Coverage: store 99.2%,
handlers 87.7%.
---ci---
project: oy
phase: 3
milestone: v0.6
status: execute
---/ci---
68 lines
2.5 KiB
HTML
68 lines
2.5 KiB
HTML
{{define "title"}}{{.Window.WindowID}} — OpenYield{{end}}
|
|
|
|
{{define "content"}}
|
|
<section class="panel">
|
|
<h1>{{.Window.WindowID}}</h1>
|
|
<table class="kv">
|
|
<tr><th>Window ID</th><td>{{.Window.WindowID}}</td></tr>
|
|
<tr><th>Grantor</th><td>{{.Window.GrantorHolder}}</td></tr>
|
|
<tr><th>Grantee</th><td>{{.Window.Grantee}}</td></tr>
|
|
<tr><th>Scope</th><td>{{.Window.Scope.Kind}} ({{.Window.Scope.ResourceID}})</td></tr>
|
|
<tr><th>Start</th><td>{{.Window.Start}}</td></tr>
|
|
<tr><th>End</th><td>{{.Window.End}}</td></tr>
|
|
<tr><th>Rate limit</th><td>{{.Window.RateLimit.ActionsConsumed}} / {{.Window.RateLimit.MaxActions}} per {{.Window.RateLimit.PerDurationSeconds}}s</td></tr>
|
|
<tr><th>Revoked</th><td>{{if .Window.Revoked}}yes{{else}}no{{end}}</td></tr>
|
|
<tr><th>Status</th><td>
|
|
{{if eq (string .Window.Status) "Open"}}<span class="badge amber">Open</span>{{end}}
|
|
{{if eq (string .Window.Status) "Active"}}<span class="badge green">Active</span>{{end}}
|
|
{{if eq (string .Window.Status) "Revoked"}}<span class="badge red">Revoked</span>{{end}}
|
|
{{if eq (string .Window.Status) "Expired"}}<span class="badge grey">Expired</span>{{end}}
|
|
</td></tr>
|
|
</table>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<h2>Lifecycle actions</h2>
|
|
<p>
|
|
{{if eq (string .Window.Status) "Open"}}
|
|
<form method="POST" action="/window/{{.Window.WindowID}}/activate" style="display:inline">
|
|
<button type="submit">Activate</button>
|
|
</form>
|
|
{{end}}
|
|
{{if or (eq (string .Window.Status) "Open") (eq (string .Window.Status) "Active")}}
|
|
<form method="POST" action="/window/{{.Window.WindowID}}/revoke" style="display:inline">
|
|
<button type="submit">Revoke</button>
|
|
</form>
|
|
{{end}}
|
|
{{if or (eq (string .Window.Status) "Open") (eq (string .Window.Status) "Active")}}
|
|
<form method="POST" action="/window/{{.Window.WindowID}}/expire" style="display:inline">
|
|
<button type="submit">Expire</button>
|
|
</form>
|
|
{{end}}
|
|
</p>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<h2>Audit log</h2>
|
|
{{if .AuditLog}}
|
|
<table>
|
|
<thead><tr><th>Entry ID</th><th>Timestamp</th><th>Action</th><th>Result</th><th>Granter</th></tr></thead>
|
|
<tbody>
|
|
{{range .AuditLog}}
|
|
<tr>
|
|
<td>{{.EntryID}}</td>
|
|
<td>{{.Timestamp}}</td>
|
|
<td>{{.Action}}</td>
|
|
<td>{{.Result}}</td>
|
|
<td>{{.GranterRef}}</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
{{else}}
|
|
<p>No audit entries yet.</p>
|
|
{{end}}
|
|
</section>
|
|
|
|
<p><a href="/window">Back to Window list</a></p>
|
|
{{end}} |