diff --git a/AGENTS.md b/AGENTS.md index eae29afd..7fc325c6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -198,7 +198,7 @@ databases. The `migrationsRequiringFKDisabled` map in Headscale enforces **tags XOR user ownership**: every node is either tagged (owned by tags) or user-owned (owned by a user namespace), never -both. This is a load-bearing architectural invariant. +both. This is a load-bearing architectural rule. - **Use `node.IsTagged()`** (`hscontrol/types/node.go:221`) to determine ownership, not `node.UserID().Valid()`. A tagged node may still have diff --git a/hscontrol/db/users_test.go b/hscontrol/db/users_test.go index 0ecbe21b..cbb1c3ce 100644 --- a/hscontrol/db/users_test.go +++ b/hscontrol/db/users_test.go @@ -100,7 +100,7 @@ func TestDestroyUserErrors(t *testing.T) { user, err := db.CreateUser(types.User{Name: "test"}) require.NoError(t, err) - // Create a tagged node with no user_id (the invariant). + // Create a tagged node with no user_id (the rule for tagged nodes). node := types.Node{ ID: 0, Hostname: "tagged-node", diff --git a/hscontrol/grpcv1_test.go b/hscontrol/grpcv1_test.go index 74a50fe0..bd4289cb 100644 --- a/hscontrol/grpcv1_test.go +++ b/hscontrol/grpcv1_test.go @@ -596,7 +596,7 @@ func TestDeleteUser_TaggedNodeSurvives(t *testing.T) { require.NoError(t, err) require.True(t, resp.MachineAuthorized) - // Verify the registered node has nil UserID (enforced invariant). + // Verify the registered node has nil UserID (enforced at registration). node, found := app.state.GetNodeByNodeKey(nodeKey.Public()) require.True(t, found) require.True(t, node.IsTagged()) diff --git a/hscontrol/policy/v2/tailscale_acl_data_compat_test.go b/hscontrol/policy/v2/tailscale_acl_data_compat_test.go index 37275f6e..18983ab9 100644 --- a/hscontrol/policy/v2/tailscale_acl_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_acl_data_compat_test.go @@ -344,7 +344,7 @@ func testACLError(t *testing.T, tf *testcapture.Capture) { } // assertACLErrorContains requires that headscale's error contains the -// Tailscale SaaS error message verbatim. Divergence means an emitter +// Tailscale SaaS error message exactly. Divergence means an emitter // needs to be aligned, not papered over with a translation table. func assertACLErrorContains( t *testing.T, diff --git a/hscontrol/policy/v2/tailscale_grants_compat_test.go b/hscontrol/policy/v2/tailscale_grants_compat_test.go index bd6f0231..7a994aab 100644 --- a/hscontrol/policy/v2/tailscale_grants_compat_test.go +++ b/hscontrol/policy/v2/tailscale_grants_compat_test.go @@ -409,7 +409,7 @@ func TestGrantsCompat(t *testing.T) { // different node IPs. nodes := buildGrantsNodesFromCapture(users, tf) - // Use the captured full policy verbatim (anonymization + // Use the captured full policy as is (anonymization // in tscap already rewrote SaaS emails). policyJSON := convertPolicyUserEmails(tf.Input.FullPolicy) @@ -457,7 +457,7 @@ func testGrantError(t *testing.T, policyJSON []byte, tf *testcapture.Capture) { } // assertGrantErrorContains requires that headscale's error contains -// the Tailscale SaaS error message verbatim. Divergence means an +// the Tailscale SaaS error message exactly. Divergence means an // emitter needs to be aligned, not papered over with a translation // table. func assertGrantErrorContains(t *testing.T, err error, wantMsg string, testID string) { diff --git a/hscontrol/policy/v2/tailscale_routes_data_compat_test.go b/hscontrol/policy/v2/tailscale_routes_data_compat_test.go index 23d38f7a..1bc0182f 100644 --- a/hscontrol/policy/v2/tailscale_routes_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_routes_data_compat_test.go @@ -1552,7 +1552,7 @@ func testRoutesError(t *testing.T, tf *testcapture.Capture) { } // assertRoutesErrorContains requires that headscale's error contains -// the Tailscale SaaS error message verbatim. Divergence means an +// the Tailscale SaaS error message exactly. Divergence means an // emitter needs to be aligned, not papered over with a translation // table. func assertRoutesErrorContains( diff --git a/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go b/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go index 8fd5d5ab..610aa95d 100644 --- a/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go @@ -204,7 +204,7 @@ func TestSSHDataCompat(t *testing.T) { // different node IPs. nodes := buildGrantsNodesFromCapture(users, tf) - // Use the captured full policy verbatim. Anonymization in + // Use the captured full policy as is. Anonymization in // tscap already rewrites SaaS emails to @example.com. policyJSON := tf.Input.FullPolicy diff --git a/hscontrol/templates/ping_test.go b/hscontrol/templates/ping_test.go index 3e80cf8f..52909cd6 100644 --- a/hscontrol/templates/ping_test.go +++ b/hscontrol/templates/ping_test.go @@ -19,7 +19,7 @@ func TestPingPageEscapesQuery(t *testing.T) { t.Run(p, func(t *testing.T) { out := PingPage(p, nil, nil).Render() if strings.Contains(out, p) { - t.Fatalf("unescaped payload rendered verbatim: %q", p) + t.Fatalf("payload rendered without escaping: %q", p) } }) } diff --git a/hscontrol/types/testcapture/header.go b/hscontrol/types/testcapture/header.go index ffc63fc1..9b29b903 100644 --- a/hscontrol/types/testcapture/header.go +++ b/hscontrol/types/testcapture/header.go @@ -13,8 +13,8 @@ import ( // // // -// Nodes with filter rules: of ← for non-SSH corpora -// Nodes with SSH rules: of ← for SSH corpora +// Nodes with filter rules: of ← for non-SSH captures +// Nodes with SSH rules: of ← for SSH captures // Captured at: // tscap version: // schema version: @@ -67,9 +67,9 @@ func CommentHeader(c *Capture) string { // non-empty captured data, or the empty string if there are no // captures at all. // -// The phrasing depends on which fields the corpus uses: -// - SSH corpora populate SSHRules -// - other corpora populate PacketFilterRules +// The phrasing depends on which fields the capture uses: +// - SSH captures populate SSHRules +// - other captures populate PacketFilterRules // // If both fields appear (mixed/unusual), filter rules wins. func captureStats(c *Capture) string { diff --git a/hscontrol/types/testcapture/testcapture.go b/hscontrol/types/testcapture/testcapture.go index 1ff69ef4..cc0ee0a0 100644 --- a/hscontrol/types/testcapture/testcapture.go +++ b/hscontrol/types/testcapture/testcapture.go @@ -12,7 +12,7 @@ // notification returns a stale Peers slice — see the comment on // Node.Netmap below) for months. // -// All four corpora (acl, routes, grant, ssh) use the same Capture +// All four capture types (acl, routes, grant, ssh) use the same Capture // shape. SSH scenarios populate Captures[name].SSHRules; the others // populate Captures[name].PacketFilterRules + Captures[name].Netmap. package testcapture @@ -36,7 +36,7 @@ const SchemaVersion = 1 // Capture is one captured run of one scenario. // -// All four corpora (acl, routes, grant, ssh) use this same shape. +// All four capture types (acl, routes, grant, ssh) use this same shape. // SSH scenarios populate Captures[name].SSHRules; the others populate // Captures[name].PacketFilterRules + Captures[name].Netmap. type Capture struct { @@ -100,7 +100,7 @@ type Capture struct { // re-marshaled to a string at load time so consumers see the typed // field uniformly. type Input struct { - // FullPolicy is the verbatim policy that was POSTed to the SaaS + // FullPolicy is the unchanged policy that was POSTed to the SaaS // API. Stored as a string because it is opaque JSON that round- // trips losslessly without parsing — headscale's policy parser // reads it on demand. @@ -116,7 +116,7 @@ type Input struct { // before pushing the policy. Tailnet TailnetInput `json:"tailnet"` - // ScenarioHuJSON is the verbatim contents of the scenario file + // ScenarioHuJSON is the unchanged contents of the scenario file // (HuJSON). Reading this back is enough to re-run the exact // same scenario. ScenarioHuJSON string `json:"scenario_hujson"` @@ -171,7 +171,7 @@ func (i *Input) UnmarshalJSON(data []byte) error { *i = Input(raw.alias) // raw.FullPolicy might be a JSON-encoded string ("...") or a JSON // object/array/null. Try string first; on failure use the raw bytes - // verbatim, normalised to compact form. + // as is, normalised to compact form. if len(raw.FullPolicy) == 0 || string(raw.FullPolicy) == "null" { i.FullPolicy = "" return nil @@ -276,7 +276,7 @@ type TopologyNode struct { // Node is the captured state for one node, keyed by GivenName in // Capture.Captures. // -// All four corpora populate the same struct. Different fields are +// All four capture types populate the same struct. Different fields are // used by different test types: // // - acl, routes, grant: PacketFilterRules + PacketFilterMatches + Netmap diff --git a/hscontrol/types/testcapture/testcapture_test.go b/hscontrol/types/testcapture/testcapture_test.go index 69a17787..e3e6282d 100644 --- a/hscontrol/types/testcapture/testcapture_test.go +++ b/hscontrol/types/testcapture/testcapture_test.go @@ -404,7 +404,7 @@ func TestCommentHeader_EmptyFilterRulesCountAsEmpty(t *testing.T) { } header := testcapture.CommentHeader(c) - // Only "b" and "c" are non-nil, so the corpus is detected as + // Only "b" and "c" are non-nil, so the capture is detected as // "filter rules" — and only "c" actually has rules. With the new // typed semantics, b's empty slice still counts as "set" (not // nil), so the denominator is 2 of 3 capture entries that have