feat: add bounded admin WebSocket backend (Phase 8D.5)
- Require current admin cookie sessions, Origin checks and single-use tickets - Reuse the shared console with session-aware authorization and slot allocation - Add HTTPD-owned I/O, bounded buffering and revocation cleanup - Prevent LRU eviction of serial clients and stale admin socket closure - Reject unsupported web-shell mutations before side effects - Add host regressions, a smoke client and resource accounting Validated by user sign-off after a 15-minute full-client soak at 230400 baud, with a few broker drops under heavy output. Browser UI remains for Phase 8D.6; numeric memory reserves remain open.
This commit is contained in:
@@ -7,6 +7,21 @@
|
||||
|
||||
static char query[48];
|
||||
static unsigned broker_connections, broker_disconnects, writes, closes;
|
||||
static unsigned admin_revocations;
|
||||
static web_session_id_t expected_invalidated_id, last_admin_id;
|
||||
static size_t last_admin_username_length;
|
||||
void web_admin_transport_revoke(web_session_id_t id, const uint8_t *username, size_t length)
|
||||
{
|
||||
assert(!host_lock_depth);
|
||||
++admin_revocations;
|
||||
last_admin_id = id;
|
||||
last_admin_username_length = username ? length : 0;
|
||||
if (expected_invalidated_id) {
|
||||
bool current = true;
|
||||
assert(web_session_store_is_current(expected_invalidated_id, ¤t) == ESP_ERR_NOT_FOUND && !current);
|
||||
expected_invalidated_id = 0;
|
||||
}
|
||||
}
|
||||
static esp_err_t close_result = ESP_OK;
|
||||
static httpd_req_t request = { .handle = (void *)1 };
|
||||
static void (*connect_hook)(void);
|
||||
@@ -96,7 +111,9 @@ int main(void) {
|
||||
assert(web_serial_transport_mint_ticket(&bob, a.view.id, ta, sizeof(ta)) != ESP_OK);
|
||||
web_serial_slot_t *sa = connect_session(&a), *sb = connect_session(&b);
|
||||
ticket_for(&a, ta);
|
||||
expected_invalidated_id = a.view.id;
|
||||
assert(web_serial_transport_revoke_web_session(a.view.id) == ESP_OK);
|
||||
assert(!expected_invalidated_id && last_admin_id == a.view.id && !last_admin_username_length);
|
||||
assert(sa->close_requested && !sb->close_requested); absent(&a); present(&b); present(&c);
|
||||
assert(consume_ticket(ta, a.view.id, &p, &consumed) == ESP_OK && !consumed);
|
||||
assert(consume_ticket(tb, b.view.id, &p, &consumed) == ESP_OK && consumed);
|
||||
@@ -107,7 +124,9 @@ int main(void) {
|
||||
issued_t d = mint(&alice); sa = connect_session(&d);
|
||||
assert(web_serial_transport_revoke_web_session(a.view.id) == ESP_OK && !sa->close_requested);
|
||||
ticket_for(&b, tb); ticket_for(&d, ta);
|
||||
expected_invalidated_id = b.view.id;
|
||||
assert(web_serial_transport_revoke_user((const uint8_t *)"alice", 5) == ESP_OK);
|
||||
assert(!expected_invalidated_id && !last_admin_id && last_admin_username_length == 5);
|
||||
assert(sa->close_requested && sb->close_requested); absent(&b); absent(&d); present(&c);
|
||||
assert(consume_ticket(ta, d.view.id, &p, &consumed) == ESP_OK && !consumed);
|
||||
assert(consume_ticket(tb, b.view.id, &p, &consumed) == ESP_OK && !consumed);
|
||||
@@ -144,10 +163,15 @@ int main(void) {
|
||||
serial_reset(); web_session_store_stop();
|
||||
assert(web_serial_transport_mint_ticket(&alice, 0, ta, sizeof(ta)) != ESP_OK);
|
||||
serial_reset(); a = mint(&alice); b = mint(&bob);
|
||||
expected_invalidated_id = a.view.id;
|
||||
assert(web_serial_transport_revoke_sessions() == ESP_OK); absent(&a); absent(&b);
|
||||
assert(!expected_invalidated_id && !last_admin_id && !last_admin_username_length);
|
||||
assert(snapshot().initialized); assert(!host_lock_depth && closes > 0);
|
||||
serial_reset(); a = mint(&alice); b = mint(&bob); s_initialized = false;
|
||||
expected_invalidated_id = a.view.id;
|
||||
unsigned notified = admin_revocations;
|
||||
assert(web_serial_transport_revoke_user((const uint8_t *)"alice", 5) == ESP_ERR_INVALID_STATE);
|
||||
assert(!expected_invalidated_id && admin_revocations == notified + 1);
|
||||
absent(&a); present(&b);
|
||||
serial_reset(); a = mint(&alice);
|
||||
for (unsigned field = 0; field < 6; ++field) {
|
||||
|
||||
Reference in New Issue
Block a user