milestone 33: contract closure — samples, file-authority enumeration, dead code, bundle ceiling

This commit is contained in:
2026-08-22 23:31:37 +02:00
parent e5f23d5466
commit 51cda8b8cb
49 changed files with 397 additions and 113 deletions
+1 -1
View File
@@ -91,7 +91,7 @@ fn confirmLogin(
/// Ends the session the cookie names. An unknown cookie is not an error: the
/// point of logging out is to end up logged out, which is where it already is.
pub fn applyLogout(state: *server.WebState, io: std.Io, cookie_header: []const u8) bool {
fn applyLogout(state: *server.WebState, io: std.Io, cookie_header: []const u8) bool {
const sessions = state.sessions orelse return false;
const value = http_util.cookieValue(cookie_header, auth.cookie_name) orelse return false;
return sessions.logout(io, value);
+4 -4
View File
@@ -85,7 +85,7 @@ pub const StatusView = struct {
// decisions
// ---------------------------------------------------------------------------
pub fn applyCreate(
fn applyCreate(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -103,7 +103,7 @@ pub fn applyCreate(
return .{ .id = id };
}
pub fn applyUpdate(
fn applyUpdate(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -121,7 +121,7 @@ pub fn applyUpdate(
return mutations.reload(state, io);
}
pub fn applyDelete(state: *server.WebState, io: std.Io, id: i64) ?Failure {
fn applyDelete(state: *server.WebState, io: std.Io, id: i64) ?Failure {
const database = mutations.requireConfigDb(state) catch return mutations.no_config_db;
state.config_lock.lockUncancelable(io);
@@ -158,7 +158,7 @@ fn pruneFiles(state: *server.WebState, io: std.Io) void {
/// `refreshAll` already ends in the manager's own reload; the seam is called
/// too, because it is how the composition root learns that a change landed and
/// the only reload a test can observe.
pub fn applyRefresh(state: *server.WebState, io: std.Io, out: []manager_mod.SourceStatus) union(enum) {
fn applyRefresh(state: *server.WebState, io: std.Io, out: []manager_mod.SourceStatus) union(enum) {
statuses: usize,
fail: Failure,
} {
+3 -3
View File
@@ -56,7 +56,7 @@ const PrefixesBody = struct {
// decisions
// ---------------------------------------------------------------------------
pub fn applyUpdate(
fn applyUpdate(
state: *server.WebState,
io: std.Io,
id: i64,
@@ -72,7 +72,7 @@ pub fn applyUpdate(
return mutations.reload(state, io);
}
pub fn applyDelete(state: *server.WebState, io: std.Io, id: i64) ?Failure {
fn applyDelete(state: *server.WebState, io: std.Io, id: i64) ?Failure {
const database = mutations.requireConfigDb(state) catch return mutations.no_config_db;
state.config_lock.lockUncancelable(io);
@@ -83,7 +83,7 @@ pub fn applyDelete(state: *server.WebState, io: std.Io, id: i64) ?Failure {
return mutations.reload(state, io);
}
pub fn applyReplacePrefixes(
fn applyReplacePrefixes(
state: *server.WebState,
io: std.Io,
arena: Allocator,
+4 -4
View File
@@ -48,7 +48,7 @@ const Created = union(enum) { id: i64, fail: Failure };
// decisions
// ---------------------------------------------------------------------------
pub fn applyCreate(
fn applyCreate(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -68,7 +68,7 @@ pub fn applyCreate(
return .{ .id = id };
}
pub fn applyUpdate(
fn applyUpdate(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -105,7 +105,7 @@ fn updateLocked(database: *db.Db, arena: Allocator, id: i64, item: model.Group)
return null;
}
pub fn applyDelete(state: *server.WebState, io: std.Io, arena: Allocator, id: i64) ?Failure {
fn applyDelete(state: *server.WebState, io: std.Io, arena: Allocator, id: i64) ?Failure {
const database = mutations.requireConfigDb(state) catch return mutations.no_config_db;
state.config_lock.lockUncancelable(io);
@@ -133,7 +133,7 @@ fn deleteLocked(database: *db.Db, arena: Allocator, id: i64) ?Failure {
return null;
}
pub fn applySetSources(
fn applySetSources(
state: *server.WebState,
io: std.Io,
id: i64,
+3 -3
View File
@@ -150,7 +150,7 @@ pub fn protection(input: Input) Protection {
};
}
pub fn queryHistoryState(input: Input) []const u8 {
fn queryHistoryState(input: Input) []const u8 {
if (input.writer_failed) return query_history_failed;
if (input.gate_episode == .losing) return query_history_losing;
return query_history_recording;
@@ -159,13 +159,13 @@ pub fn queryHistoryState(input: Input) []const u8 {
/// The operational log is not recording — either the store never opened or its
/// writes are failing. Both mean the same thing to an operator: the record of
/// what went wrong is not being kept.
pub fn diagnosticsUnavailable(input: Input) bool {
fn diagnosticsUnavailable(input: Input) bool {
return !input.diagnostics_present or input.diagnostics_write_failed;
}
/// `warn` reads as a log level rather than as a quantity of disk. The monitor
/// keeps its own name; the wire says what an operator sees on the page.
pub fn diskState(state: disk_monitor.State) []const u8 {
fn diskState(state: disk_monitor.State) []const u8 {
return switch (state) {
.ok => disk_ok,
.warn => disk_low,
+1 -1
View File
@@ -47,7 +47,7 @@ pub fn view(entry: *const sse.Entry) EventView {
/// One `event: query` frame. JSON never contains a raw newline, so the whole
/// payload is a single `data:` line.
pub fn writeEvent(w: *std.Io.Writer, entry: *const sse.Entry) std.Io.Writer.Error!void {
fn writeEvent(w: *std.Io.Writer, entry: *const sse.Entry) std.Io.Writer.Error!void {
try w.writeAll("event: query\ndata: ");
var stringify: std.json.Stringify = .{ .writer = w };
try stringify.write(view(entry));
+6 -6
View File
@@ -88,7 +88,7 @@ fn publish(state: *server.WebState, io: std.Io, arena: Allocator, database: *@im
return mutations.reload(state, io);
}
pub fn applyCreateRecord(
fn applyCreateRecord(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -106,7 +106,7 @@ pub fn applyCreateRecord(
return .{ .id = id };
}
pub fn applyUpdateRecord(
fn applyUpdateRecord(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -124,7 +124,7 @@ pub fn applyUpdateRecord(
return publish(state, io, arena, database);
}
pub fn applyDeleteRecord(state: *server.WebState, io: std.Io, arena: Allocator, id: i64) ?Failure {
fn applyDeleteRecord(state: *server.WebState, io: std.Io, arena: Allocator, id: i64) ?Failure {
const database = mutations.requireConfigDb(state) catch return mutations.no_config_db;
state.config_lock.lockUncancelable(io);
@@ -139,7 +139,7 @@ pub fn applyDeleteRecord(state: *server.WebState, io: std.Io, arena: Allocator,
// forward zones: decisions
// ---------------------------------------------------------------------------
pub fn applyCreateZone(
fn applyCreateZone(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -157,7 +157,7 @@ pub fn applyCreateZone(
return .{ .id = id };
}
pub fn applyUpdateZone(
fn applyUpdateZone(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -175,7 +175,7 @@ pub fn applyUpdateZone(
return publish(state, io, arena, database);
}
pub fn applyDeleteZone(state: *server.WebState, io: std.Io, arena: Allocator, id: i64) ?Failure {
fn applyDeleteZone(state: *server.WebState, io: std.Io, arena: Allocator, id: i64) ?Failure {
const database = mutations.requireConfigDb(state) catch return mutations.no_config_db;
state.config_lock.lockUncancelable(io);
-7
View File
@@ -390,12 +390,6 @@ pub fn checkSource(arena: Allocator, source: model.BlocklistSource) error{OutOfM
return firstProblem(arena, cfg);
}
pub fn checkClientIp(arena: Allocator, ip: []const u8) error{OutOfMemory}!?[]const u8 {
var cfg = skeleton(&default_groups);
cfg.clients = &.{.{ .ip = ip, .group = skeleton_group }};
return firstProblem(arena, cfg);
}
pub fn checkClientPrefix(arena: Allocator, prefix: []const u8, priority: i32) error{OutOfMemory}!?[]const u8 {
var cfg = skeleton(&default_groups);
cfg.client_prefixes = &.{.{ .prefix = prefix, .group = skeleton_group, .priority = priority }};
@@ -625,7 +619,6 @@ test "a valid candidate row reports no problem" {
try checkForwardZone(arena, .{ .zone = "lan", .resolver = "udp://10.0.0.1:53" }),
);
try testing.expectEqual(@as(?[]const u8, null), try checkRule(arena, "*.ads.example", .wildcard));
try testing.expectEqual(@as(?[]const u8, null), try checkClientIp(arena, "192.168.1.10"));
try testing.expectEqual(@as(?[]const u8, null), try checkClientPrefix(arena, "192.168.1.0/24", 100));
try testing.expectEqual(@as(?[]const u8, null), try checkGroupName(arena, "kids"));
try testing.expectEqual(@as(?[]const u8, null), try checkGroupName(arena, "default"));
+1 -1
View File
@@ -43,7 +43,7 @@ pub fn view(pause: *const pause_mod.Pause, now_s: i64) View {
return .{ .paused = true, .until = until };
}
pub fn apply(
fn apply(
state: *server.WebState,
io: std.Io,
body: Body,
+3 -3
View File
@@ -54,7 +54,7 @@ fn toInput(body: Body) union(enum) { input: rules_repo.RuleInput, fail: Failure
// decisions
// ---------------------------------------------------------------------------
pub fn applyCreate(
fn applyCreate(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -74,7 +74,7 @@ pub fn applyCreate(
return .{ .id = id };
}
pub fn applyUpdate(
fn applyUpdate(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -94,7 +94,7 @@ pub fn applyUpdate(
return mutations.reload(state, io);
}
pub fn applyDelete(state: *server.WebState, io: std.Io, id: i64) ?Failure {
fn applyDelete(state: *server.WebState, io: std.Io, id: i64) ?Failure {
const database = mutations.requireConfigDb(state) catch return mutations.no_config_db;
state.config_lock.lockUncancelable(io);
+1 -1
View File
@@ -309,7 +309,7 @@ pub fn view(cfg: model.Config) View {
/// Reads, merges, validates, writes, and — when the password changed — ends
/// every session. Returns the configuration as it now stands.
pub fn applyPut(
fn applyPut(
state: *server.WebState,
io: std.Io,
arena: Allocator,
+1 -1
View File
@@ -385,7 +385,7 @@ pub const PeriodError = error{BadPeriod};
/// An absent `period` is the default; anything else it cannot read is a 400,
/// never a silent fallback — a typo must not return a window nobody asked for.
pub fn periodParam(query: []const u8) PeriodError!Period {
fn periodParam(query: []const u8) PeriodError!Period {
var buf: [8]u8 = undefined;
const found = http_util.queryValue(query, "period", &buf) catch return error.BadPeriod;
const text = found orelse return default_period;
+3 -3
View File
@@ -38,7 +38,7 @@ const Created = union(enum) { id: i64, fail: Failure };
// decisions
// ---------------------------------------------------------------------------
pub fn applyCreate(
fn applyCreate(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -59,7 +59,7 @@ pub fn applyCreate(
return .{ .id = id };
}
pub fn applyUpdate(
fn applyUpdate(
state: *server.WebState,
io: std.Io,
arena: Allocator,
@@ -94,7 +94,7 @@ pub fn applyUpdate(
/// The last enabled upstream cannot go: a resolver with nowhere to forward to
/// answers nothing, and `validate.validate` refuses that configuration at
/// startup — so allowing it here would only produce a box that will not boot.
pub fn applyDelete(state: *server.WebState, io: std.Io, arena: Allocator, id: i64) ?Failure {
fn applyDelete(state: *server.WebState, io: std.Io, arena: Allocator, id: i64) ?Failure {
const database = mutations.requireConfigDb(state) catch return mutations.no_config_db;
state.config_lock.lockUncancelable(io);