Phases 11, 12: mcrctl CLI tool and mcr-web UI
Phase 11 implements the admin CLI with dual REST/gRPC transport, global flags (--server, --grpc, --token, --ca-cert, --json), and all commands: status, repo list/delete, policy CRUD, audit tail, gc trigger/status/reconcile, and snapshot. Phase 12 implements the HTMX web UI with chi router, session-based auth (HttpOnly/Secure/SameSite=Strict cookies), CSRF protection (HMAC-SHA256 signed double-submit), and pages for dashboard, repositories, manifest detail, policy management, and audit log. Security: CSRF via signed double-submit cookie, session cookies with HttpOnly/Secure/SameSite=Strict, TLS 1.3 minimum on all connections, form body size limits via http.MaxBytesReader. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
92
web/templates/policies.html
Normal file
92
web/templates/policies.html
Normal file
@@ -0,0 +1,92 @@
|
||||
{{define "title"}}Policies{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<h1>Policy Rules</h1>
|
||||
|
||||
{{if .Error}}
|
||||
<div class="error">{{.Error}}</div>
|
||||
{{end}}
|
||||
|
||||
<h2>Create Policy Rule</h2>
|
||||
<form method="POST" action="/policies">
|
||||
<input type="hidden" name="_csrf" value="{{.CSRFToken}}">
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="priority">Priority</label>
|
||||
<input type="number" id="priority" name="priority" value="100" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<input type="text" id="description" name="description" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="effect">Effect</label>
|
||||
<select id="effect" name="effect">
|
||||
<option value="allow">Allow</option>
|
||||
<option value="deny">Deny</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="actions">Actions (comma-sep)</label>
|
||||
<input type="text" id="actions" name="actions" placeholder="pull,push">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="repositories">Repositories (comma-sep)</label>
|
||||
<input type="text" id="repositories" name="repositories" placeholder="*">
|
||||
</div>
|
||||
<button type="submit">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="policy-table">
|
||||
{{if .Policies}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Priority</th>
|
||||
<th>Description</th>
|
||||
<th>Effect</th>
|
||||
<th>Actions</th>
|
||||
<th>Repositories</th>
|
||||
<th>Enabled</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Policies}}
|
||||
<tr id="policy-{{.Id}}">
|
||||
<td>{{.Id}}</td>
|
||||
<td>{{.Priority}}</td>
|
||||
<td>{{.Description}}</td>
|
||||
<td><span class="badge badge-{{.Effect}}">{{.Effect}}</span></td>
|
||||
<td>{{joinStrings .Actions ", "}}</td>
|
||||
<td>{{joinStrings .Repositories ", "}}</td>
|
||||
<td>
|
||||
{{if .Enabled}}
|
||||
<span class="badge badge-enabled">Enabled</span>
|
||||
{{else}}
|
||||
<span class="badge badge-disabled">Disabled</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td>
|
||||
<form method="POST" action="/policies/{{.Id}}/toggle" style="display:inline;">
|
||||
<input type="hidden" name="_csrf" value="{{$.CSRFToken}}">
|
||||
<button type="submit" class="small secondary">
|
||||
{{if .Enabled}}Disable{{else}}Enable{{end}}
|
||||
</button>
|
||||
</form>
|
||||
<form method="POST" action="/policies/{{.Id}}/delete" style="display:inline;">
|
||||
<input type="hidden" name="_csrf" value="{{$.CSRFToken}}">
|
||||
<button type="submit" class="small danger">Delete</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p>No policy rules configured.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user