Add claim proxy, traffic protection, session fixes #81

Merged
smell-of-curry merged 3 commits from claim-managment-upgrades into main 2026-07-16 15:29:12 +00:00
smell-of-curry commented 2026-07-15 00:23:25 +00:00 (Migrated from github.com)

Introduce a full claim proxy and traffic-protection system plus related session/server/entity improvements. Added a claim package (factory, service, snapshot, model, metrics, tests) with HTTP revalidation, immutable snapshots, fail-open semantics, and policy golden fixtures. Implement deny block, deny-rendering of subchunks, corrective chunk logic, and claim decision helpers used by many new session packet handlers. Add per-session traffic rate limiting, traffic metrics, XUID reservation to prevent duplicate logins, improved entity tracking, config fields/defaults, and numerous tests. CI updated to run go test -race and policy JSON included in repo.

Needs: https://github.com/smell-of-curry/bds-manager/pull/10 and https://github.com/smell-of-curry/pokebedrock-beh/pull/670

Summary by CodeRabbit

  • New Features

    • Added configurable claim-based protection for block interactions, rendering, item actions, and feature-specific permissions.
    • Added claim snapshot refreshing, stale-data handling, and policy configuration.
    • Added traffic protection limits for chat, commands, forms, and inventory actions.
    • Added duplicate-login prevention for simultaneous sessions.
    • Added entity tracking improvements and support for updated game-state events.
    • Added periodic traffic and claim metrics output.
  • Bug Fixes

    • Improved handling of malformed packets, invalid claims, authentication errors, and service interruptions.
Introduce a full claim proxy and traffic-protection system plus related session/server/entity improvements. Added a claim package (factory, service, snapshot, model, metrics, tests) with HTTP revalidation, immutable snapshots, fail-open semantics, and policy golden fixtures. Implement deny block, deny-rendering of subchunks, corrective chunk logic, and claim decision helpers used by many new session packet handlers. Add per-session traffic rate limiting, traffic metrics, XUID reservation to prevent duplicate logins, improved entity tracking, config fields/defaults, and numerous tests. CI updated to run go test -race and policy JSON included in repo. Needs: https://github.com/smell-of-curry/bds-manager/pull/10 and https://github.com/smell-of-curry/pokebedrock-beh/pull/670 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added configurable claim-based protection for block interactions, rendering, item actions, and feature-specific permissions. * Added claim snapshot refreshing, stale-data handling, and policy configuration. * Added traffic protection limits for chat, commands, forms, and inventory actions. * Added duplicate-login prevention for simultaneous sessions. * Added entity tracking improvements and support for updated game-state events. * Added periodic traffic and claim metrics output. * **Bug Fixes** * Improved handling of malformed packets, invalid claims, authentication errors, and service interruptions. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
coderabbitai[bot] commented 2026-07-15 00:23:43 +00:00 (Migrated from github.com)

Review Change Stack

Warning

Review limit reached

@smell-of-curry, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3c3a40aa-87c1-4b95-9a9a-65777869881a

📥 Commits

Reviewing files that changed from the base of the PR and between 5a9da19152 and 4a90aa66ba.

📒 Files selected for processing (13)
  • AGENTS.md
  • gobds/claim/metrics.go
  • gobds/claim/service.go
  • gobds/claim/snapshot.go
  • gobds/session/claim_policy_golden_test.go
  • gobds/session/handler_inventory_transaction.go
  • gobds/session/handler_sub_chunk.go
  • gobds/session/handler_text.go
  • gobds/session/handler_update_abilities.go
  • gobds/session/traffic.go
  • gobds/session/util_claim_action.go
  • gobds/session/util_claim_action_test.go
  • policy/claim_policy.v1.json
📝 Walkthrough

Walkthrough

Adds immutable claim snapshots, feature-based authorization, traffic protection, metrics, entity tracking, duplicate-XUID admission, rendering corrections, expanded session handlers, configuration, and comprehensive tests.

Changes

Claims and session hardening

Layer / File(s) Summary
Claim contracts and configuration
gobds/claim/*, gobds/config.go, gobds/user_config.go, config.example.toml, policy/*, gobds/block/*
Adds claim features, snapshot indexing and validation, deny-block registration, runtime configuration, defaults, and policy fixtures.
Claim refresh and metrics
gobds/claim/factory.go, gobds/claim/service.go, gobds/claim/metrics.go
Adds conditional HTTP refresh, immutable snapshot replacement, stale/failure status handling, and atomic JSON delta metrics.
Entity and session state
gobds/entity/*, gobds/session/config.go, gobds/session/data.go, gobds/session/handler_*
Tracks entity unique IDs and positions, synchronizes game mode/operator state, resolves dimensions, and wires additional packet handlers.
Claim enforcement
gobds/session/util_claim_action.go, gobds/session/handler_inventory_transaction.go, gobds/session/handler_player_auth_input.go, gobds/session/handler_sub_chunk.go
Evaluates claim actions and applies permission filtering to inventory actions, block breaks, corrective chunks, and rendered sub-chunks.
Traffic and admission controls
gobds/session/traffic.go, gobds/session/session.go, gobds/server.go, gobds/gobds.go
Adds token-bucket limits, malformed-packet handling, traffic reporting, duplicate-XUID reservations, and expanded startup/session wiring.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Session
  participant ClaimFactory
  participant Snapshot
  participant World
  Client->>Session: Send protected packet
  Session->>ClaimFactory: Query snapshot and claim candidates
  ClaimFactory->>Snapshot: Return indexed candidates
  Session->>World: Apply deny block or corrective response
  World-->>Client: Filtered packet or correction

Possibly related PRs

Suggested reviewers: glancist

🚥 Pre-merge checks | 4 | 1

Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title is concise and accurately reflects the main additions: claim proxy, traffic protection, and session-related fixes.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claim-managment-upgrades

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- review_stack_entry_start --> [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/smell-of-curry/gobds/pull/81?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- This is an auto-generated comment: rate limited by coderabbit.ai --> > [!WARNING] > ## Review limit reached > > `@smell-of-curry`, you've reached your PR review limit, so we couldn't start this review. > > **Next review available in:** **49 minutes** > > Enable **[usage-based reviews](https://app.coderabbit.ai/settings/billing?tab=usage&orgId=622c78ce-9e11-4f9b-9f86-5799be0786e4)** in Billing to review now. Otherwise, wait until the next included review is available. > You're only billed for reviews past your plan's rate limits ($0.25/file). > > <details> > <summary>How can I continue?</summary> > > After more reviews become available, a review can be triggered using the `@coderabbitai review` command as a PR comment. Alternatively, push new commits to this PR. > > To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. > > </details> > > > <details> > <summary>How do review limits work?</summary> > > CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. > > For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. > > Please refer [docs](https://docs.coderabbit.ai/management/plans#rate-limits) for additional details. > > </details> > > <details> > <summary>Review details</summary> > > <details> > <summary>⚙️ Run configuration</summary> > > **Configuration used**: defaults > > **Review profile**: CHILL > > **Plan**: Pro > > **Run ID**: `3c3a40aa-87c1-4b95-9a9a-65777869881a` > > </details> > > <details> > <summary>📥 Commits</summary> > > Reviewing files that changed from the base of the PR and between 5a9da191529ad93c7108fc9c71cadf42052ac3f3 and 4a90aa66ba80731c39930293353aad75b3f48777. > > </details> > > <details> > <summary>📒 Files selected for processing (13)</summary> > > * `AGENTS.md` > * `gobds/claim/metrics.go` > * `gobds/claim/service.go` > * `gobds/claim/snapshot.go` > * `gobds/session/claim_policy_golden_test.go` > * `gobds/session/handler_inventory_transaction.go` > * `gobds/session/handler_sub_chunk.go` > * `gobds/session/handler_text.go` > * `gobds/session/handler_update_abilities.go` > * `gobds/session/traffic.go` > * `gobds/session/util_claim_action.go` > * `gobds/session/util_claim_action_test.go` > * `policy/claim_policy.v1.json` > > </details> > > </details> <!-- end of auto-generated comment: rate limited by coderabbit.ai --> <!-- walkthrough_start --> <details> <summary>📝 Walkthrough</summary> ## Walkthrough Adds immutable claim snapshots, feature-based authorization, traffic protection, metrics, entity tracking, duplicate-XUID admission, rendering corrections, expanded session handlers, configuration, and comprehensive tests. ### Changes **Claims and session hardening** |Layer / File(s)|Summary| |---|---| |**Claim contracts and configuration** <br> `gobds/claim/*`, `gobds/config.go`, `gobds/user_config.go`, `config.example.toml`, `policy/*`, `gobds/block/*`|Adds claim features, snapshot indexing and validation, deny-block registration, runtime configuration, defaults, and policy fixtures.| |**Claim refresh and metrics** <br> `gobds/claim/factory.go`, `gobds/claim/service.go`, `gobds/claim/metrics.go`|Adds conditional HTTP refresh, immutable snapshot replacement, stale/failure status handling, and atomic JSON delta metrics.| |**Entity and session state** <br> `gobds/entity/*`, `gobds/session/config.go`, `gobds/session/data.go`, `gobds/session/handler_*`|Tracks entity unique IDs and positions, synchronizes game mode/operator state, resolves dimensions, and wires additional packet handlers.| |**Claim enforcement** <br> `gobds/session/util_claim_action.go`, `gobds/session/handler_inventory_transaction.go`, `gobds/session/handler_player_auth_input.go`, `gobds/session/handler_sub_chunk.go`|Evaluates claim actions and applies permission filtering to inventory actions, block breaks, corrective chunks, and rendered sub-chunks.| |**Traffic and admission controls** <br> `gobds/session/traffic.go`, `gobds/session/session.go`, `gobds/server.go`, `gobds/gobds.go`|Adds token-bucket limits, malformed-packet handling, traffic reporting, duplicate-XUID reservations, and expanded startup/session wiring.| **Estimated code review effort:** 5 (Critical) | ~120 minutes ### Sequence Diagram(s) ```mermaid sequenceDiagram participant Client participant Session participant ClaimFactory participant Snapshot participant World Client->>Session: Send protected packet Session->>ClaimFactory: Query snapshot and claim candidates ClaimFactory->>Snapshot: Return indexed candidates Session->>World: Apply deny block or corrective response World-->>Client: Filtered packet or correction ``` **Possibly related PRs** - [smell-of-curry/gobds#16](https://github.com/smell-of-curry/gobds/pull/16): Provides the GoBDS lifecycle and accept/start-game wiring extended here. - [smell-of-curry/gobds#42](https://github.com/smell-of-curry/gobds/pull/42): Covers earlier claim factory and claim lookup wiring evolved by this snapshot-based implementation. **Suggested reviewers:** `glancist` </details> <!-- walkthrough_end --> <!-- pre_merge_checks_walkthrough_start --> <details> <summary>🚥 Pre-merge checks | ✅ 4 | ❌ 1</summary> ### ❌ Failed checks (1 warning) | Check name | Status | Explanation | Resolution | | :----------------: | :--------- | :------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------- | | Docstring Coverage | ⚠️ Warning | Docstring coverage is 22.39% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. | <details> <summary>✅ Passed checks (4 passed)</summary> | Check name | Status | Explanation | | :------------------------: | :------- | :--------------------------------------------------------------------------------------------------------------------------- | | Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. | | Title check | ✅ Passed | The title is concise and accurately reflects the main additions: claim proxy, traffic protection, and session-related fixes. | | Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. | | Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. | </details> </details> <!-- pre_merge_checks_walkthrough_end --> <!-- finishing_touch_checkbox_start --> <details> <summary>✨ Finishing Touches</summary> <details> <summary>🧪 Generate unit tests (beta)</summary> - [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests - [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Commit unit tests in branch `claim-managment-upgrades` </details> </details> <!-- finishing_touch_checkbox_end --> <!-- tips_start --> --- Thanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=smell-of-curry/gobds&utm_content=81)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. <details> <summary>❤️ Share</summary> - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code) </details> <sub>Comment `@coderabbitai help` to get the list of available commands.</sub> <!-- tips_end -->
coderabbitai[bot] (Migrated from github.com) reviewed 2026-07-15 00:37:08 +00:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 7

🧹 Nitpick comments (5)
gobds/session/handler_sub_chunk.go (1)

71-79: 🚀 Performance & Scalability | 🔵 Trivial | Quick win

Hoist invariant dimension-range lookup out of the per-entry loop.

dimensionRangeByID(pkt.Dimension, dimensions) depends only on pkt.Dimension/dimensions, both constant for the whole packet, yet it's recomputed on every iteration of the pkt.SubChunkEntries loop. Move this (and the rangeFound check) above the loop.

♻️ Proposed fix
+	dimensionRange, rangeFound := dimensionRangeByID(pkt.Dimension, dimensions)
 	entries := make([]protocol.SubChunkEntry, 0, len(pkt.SubChunkEntries))
 	for _, entry := range pkt.SubChunkEntries {
 		...
-		dimensionRange, rangeFound := dimensionRangeByID(pkt.Dimension, dimensions)
 		// GoBDS disables the backend blob cache, ...
 		if entry.Result != protocol.SubChunkResultSuccess || !rangeFound || !dimensionFound ||
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/session/handler_sub_chunk.go` around lines 71 - 79, Move the invariant
dimensionRangeByID lookup for pkt.Dimension and dimensions, including
rangeFound, before the pkt.SubChunkEntries loop. Reuse those results in the
per-entry condition while preserving the existing append-and-continue behavior
for unsuccessful entries, missing dimensions or ranges, non-ready snapshots, and
cache-enabled packets.
gobds/claim/metrics.go (1)

54-57: 📐 Maintainability & Code Quality | 🔵 Trivial | Quick win

Add doc comments to exported one-liner methods (lint failures).

CI flags RefreshAttempt, RefreshSuccess, RefreshFailure, Packet, and Correction as exported methods missing doc comments; the same applies to SubchunkDecoded/SubchunkModified/SubchunkError for consistency with the rest of the file's style.

📝 Proposed fix
+// RefreshAttempt records one claim-refresh attempt.
 func (m *Metrics) RefreshAttempt() { m.refreshAttempts.Add(1) }
+// RefreshSuccess records one successful claim refresh.
 func (m *Metrics) RefreshSuccess() { m.refreshSuccess.Add(1) }
+// RefreshFailure records one failed claim refresh.
 func (m *Metrics) RefreshFailure() { m.refreshFailure.Add(1) }
+// Packet records one processed packet.
 func (m *Metrics) Packet()         { m.packets.Add(1) }
...
+// Correction records whether a corrective packet was sent or skipped.
 func (m *Metrics) Correction(sent bool) {

Also applies to: 106-106, 114-116

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/claim/metrics.go` around lines 54 - 57, Add Go doc comments for the
exported Metrics methods RefreshAttempt, RefreshSuccess, RefreshFailure, Packet,
Correction, SubchunkDecoded, SubchunkModified, and SubchunkError, briefly
describing each method’s counter-increment behavior and starting each comment
with the corresponding method name to satisfy lint.

Source: Linters/SAST tools

gobds/session/traffic.go (1)

73-130: 📐 Maintainability & Code Quality | 🔵 Trivial | Quick win

Reduce WithDefaults cyclomatic complexity to satisfy the lint gate.

The gocyclo check is failing on this function (complexity 19 > 15) due to the repeated if x <= 0 { x = default } pattern across 16 fields.

♻️ Suggested refactor using small default-filling helpers
+func setDefaultRate(v *float64, def float64) {
+	if *v <= 0 {
+		*v = def
+	}
+}
+
+func setDefaultBurst(v *int, def int) {
+	if *v <= 0 {
+		*v = def
+	}
+}
+
 func (c TrafficConfig) WithDefaults() TrafficConfig {
 	defaults := DefaultTrafficConfig()
-	if c.Chat.Rate <= 0 {
-		c.Chat.Rate = defaults.Chat.Rate
-	}
-	if c.Chat.Burst <= 0 {
-		c.Chat.Burst = defaults.Chat.Burst
-	}
-	... (repeat for every field) ...
+	setDefaultRate(&c.Chat.Rate, defaults.Chat.Rate)
+	setDefaultBurst(&c.Chat.Burst, defaults.Chat.Burst)
+	setDefaultRate(&c.Commands.Rate, defaults.Commands.Rate)
+	setDefaultBurst(&c.Commands.Burst, defaults.Commands.Burst)
+	setDefaultRate(&c.ModalFormResponses.Rate, defaults.ModalFormResponses.Rate)
+	setDefaultBurst(&c.ModalFormResponses.Burst, defaults.ModalFormResponses.Burst)
+	setDefaultRate(&c.InventoryTransactions.Rate, defaults.InventoryTransactions.Rate)
+	setDefaultBurst(&c.InventoryTransactions.Burst, defaults.InventoryTransactions.Burst)
+	setDefaultRate(&c.ItemStackRequests.Rate, defaults.ItemStackRequests.Rate)
+	setDefaultBurst(&c.ItemStackRequests.Burst, defaults.ItemStackRequests.Burst)
+	setDefaultBurst(&c.MaxTextBytes, defaults.MaxTextBytes)
+	setDefaultBurst(&c.MaxCommandBytes, defaults.MaxCommandBytes)
+	setDefaultBurst(&c.MaxFormResponseBytes, defaults.MaxFormResponseBytes)
+	setDefaultBurst(&c.MaxFormResponseValues, defaults.MaxFormResponseValues)
+	setDefaultBurst(&c.MaxInventoryActions, defaults.MaxInventoryActions)
+	setDefaultBurst(&c.MaxStackRequests, defaults.MaxStackRequests)
+	setDefaultBurst(&c.MaxStackActions, defaults.MaxStackActions)
+	setDefaultBurst(&c.MaxTotalStackActions, defaults.MaxTotalStackActions)
 	return c
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/session/traffic.go` around lines 73 - 130, Reduce the cyclomatic
complexity of TrafficConfig.WithDefaults by extracting the repeated
non-positive-value defaulting logic into small reusable helper functions, then
use those helpers for the rate, burst, and limit fields. Preserve the existing
DefaultTrafficConfig values and <= 0 replacement behavior for all fields.

Source: Linters/SAST tools

gobds/session/claim_policy_golden_test.go (1)

62-85: 📐 Maintainability & Code Quality | 🔵 Trivial | Quick win

Fail loudly on unrecognized action values instead of silently defaulting.

claimActionFromGolden maps unknown strings to ClaimAction(255), which isn't handled in ClaimActionPermitted's switch and falls through to the default return true. A typo in a fixture's action field would silently pass unless the fixture also expects permitted:false.

♻️ Proposed fix
-func claimActionFromGolden(value string) ClaimAction {
+func claimActionFromGolden(t *testing.T, value string) ClaimAction {
 	switch value {
 	case "render":
 		return ClaimActionRender
@@
 	case "itemDrop":
 		return ClaimActionItemDrop
 	default:
-		return ClaimAction(255)
+		t.Fatalf("unknown golden action: %q", value)
+		return 0
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/session/claim_policy_golden_test.go` around lines 62 - 85, Update
claimActionFromGolden to fail loudly when given an unrecognized action string
instead of returning ClaimAction(255). Use the test’s existing failure mechanism
to report the invalid fixture value, while preserving all recognized action
mappings and ensuring the function cannot silently produce a value that
ClaimActionPermitted treats as permitted.
gobds/claim/snapshot.go (1)

54-59: 🩺 Stability & Availability | 🔵 Trivial | Quick win

Candidates() returns mutable pointers from an "immutable" snapshot.

The struct comment promises immutability and lock-free concurrent reads, but Candidates hands back *PlayerClaim pointers into the snapshot's own backing slice/cells map. Any downstream mutation through one of these pointers (accidental or otherwise) would corrupt state shared across concurrent sessions and across snapshot generations (the 304-revalidation path in factory.go reuses the same claims/cells backing data). Consider returning value copies, or making the contract explicit (doc comment + code review checklist) that callers must treat returned claims as read-only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/claim/snapshot.go` around lines 54 - 59, Update Snapshot.Candidates to
return independent PlayerClaim value copies rather than pointers into the
snapshot’s cells backing data. Preserve nil and empty-result behavior, and
adjust affected callers to consume the copied values while keeping Snapshot’s
immutable, lock-free read contract intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gobds/claim/service.go`:
- Around line 33-113: Reduce FetchClaims complexity by extracting the HTTP
response status handling into a dedicated helper, preserving the existing
behavior for successful, not-modified, rate-limited, decode-failure, and
unexpected-status responses. Have the helper manage response.Body closure and
context cancellation and return the result, error, and retry decision so
FetchClaims retains only request/retry orchestration.
- Around line 86-90: Update the 200 OK handling in the fetch method so
s.lastModified is only replaced when the response’s last-modified header is
non-empty, matching the guard used in the 304 branch. Preserve the previously
cached value for header-less responses while continuing to return it in
FetchResult.LastModified.

In `@gobds/session/handler_sub_chunk.go`:
- Around line 20-99: Reduce cyclomatic complexity in SubChunkHandler.Handle by
extracting snapshot and dimension resolution into a helper, and moving per-entry
border and claim filtering into a separate helper. Keep Handle responsible for
instrumentation, context validation, panic recovery, setup, and assigning the
filtered entries, while preserving all existing filtering, metrics, and
fail-open behavior.
- Around line 111-156: Update applyClaimDenyBlocks to process every section in
the visible dimension Y range instead of returning unless sectionY equals
dimensionRange.Min(). For each denied x/z position, rewrite the corresponding
blocks across all relevant local Y layers rather than hard-coding SetBlock’s y
argument to 0, while preserving the existing claim checks, metrics, and payload
handling.

In `@gobds/session/handler_update_abilities.go`:
- Around line 30-40: Update the refresh logic in the handler method containing
SetOperator to call the shared correctiveLevelChunk helper instead of
constructing packet.LevelChunk directly. Pass the current position as required
by the helper so Dimension and HighestSubChunk are populated and the refresh
targets the correct dimension.

In `@gobds/session/session.go`:
- Around line 444-447: Update Session.WriteTrafficMetrics so it does not pass
the raw IdentityData().XUID to TrafficMetrics.WriteDelta; apply the project’s
approved redaction, hashing, or truncation mechanism before emitting the session
field, or require the established explicit configuration flag for raw
identifiers if that is the supported policy.

In `@gobds/session/util_claim_action.go`:
- Around line 47-84: Reduce the cyclomatic complexity of ClaimActionPermitted
below the gocyclo threshold by extracting per-action special-case logic,
including admin-claim "*" handling for block interaction, entity interaction,
and item drops, into small named helpers. Preserve all existing action outcomes
and keep ClaimActionPermitted responsible for dispatching each ClaimAction to
the appropriate helper.

---

Nitpick comments:
In `@gobds/claim/metrics.go`:
- Around line 54-57: Add Go doc comments for the exported Metrics methods
RefreshAttempt, RefreshSuccess, RefreshFailure, Packet, Correction,
SubchunkDecoded, SubchunkModified, and SubchunkError, briefly describing each
method’s counter-increment behavior and starting each comment with the
corresponding method name to satisfy lint.

In `@gobds/claim/snapshot.go`:
- Around line 54-59: Update Snapshot.Candidates to return independent
PlayerClaim value copies rather than pointers into the snapshot’s cells backing
data. Preserve nil and empty-result behavior, and adjust affected callers to
consume the copied values while keeping Snapshot’s immutable, lock-free read
contract intact.

In `@gobds/session/claim_policy_golden_test.go`:
- Around line 62-85: Update claimActionFromGolden to fail loudly when given an
unrecognized action string instead of returning ClaimAction(255). Use the test’s
existing failure mechanism to report the invalid fixture value, while preserving
all recognized action mappings and ensuring the function cannot silently produce
a value that ClaimActionPermitted treats as permitted.

In `@gobds/session/handler_sub_chunk.go`:
- Around line 71-79: Move the invariant dimensionRangeByID lookup for
pkt.Dimension and dimensions, including rangeFound, before the
pkt.SubChunkEntries loop. Reuse those results in the per-entry condition while
preserving the existing append-and-continue behavior for unsuccessful entries,
missing dimensions or ranges, non-ready snapshots, and cache-enabled packets.

In `@gobds/session/traffic.go`:
- Around line 73-130: Reduce the cyclomatic complexity of
TrafficConfig.WithDefaults by extracting the repeated non-positive-value
defaulting logic into small reusable helper functions, then use those helpers
for the rate, burst, and limit fields. Preserve the existing
DefaultTrafficConfig values and <= 0 replacement behavior for all fields.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b0887fe4-19e6-40eb-b4e4-450a3bd26ffb

📥 Commits

Reviewing files that changed from the base of the PR and between 8e4a5764e7 and 5a9da19152.

📒 Files selected for processing (55)
  • .github/workflows/lint.yml
  • .gitignore
  • config.example.toml
  • gobds/block/deny.go
  • gobds/block/factory.go
  • gobds/block/hash.go
  • gobds/claim/factory.go
  • gobds/claim/factory_test.go
  • gobds/claim/metrics.go
  • gobds/claim/metrics_test.go
  • gobds/claim/model.go
  • gobds/claim/model_test.go
  • gobds/claim/service.go
  • gobds/claim/service_test.go
  • gobds/claim/snapshot.go
  • gobds/claim/snapshot_test.go
  • gobds/config.go
  • gobds/config_test.go
  • gobds/entity/entity.go
  • gobds/entity/factory.go
  • gobds/entity/factory_test.go
  • gobds/gobds.go
  • gobds/server.go
  • gobds/server_test.go
  • gobds/service/authentication/service.go
  • gobds/service/vpn/service.go
  • gobds/session/claim_policy_golden_test.go
  • gobds/session/config.go
  • gobds/session/data.go
  • gobds/session/handler_add_actor.go
  • gobds/session/handler_add_painting.go
  • gobds/session/handler_change_dimension.go
  • gobds/session/handler_command_request.go
  • gobds/session/handler_inventory_transaction.go
  • gobds/session/handler_inventory_transaction_test.go
  • gobds/session/handler_item_registry.go
  • gobds/session/handler_item_stack_request.go
  • gobds/session/handler_modal_form_response.go
  • gobds/session/handler_move_actor.go
  • gobds/session/handler_player_auth_input.go
  • gobds/session/handler_player_auth_input_test.go
  • gobds/session/handler_remove_actor.go
  • gobds/session/handler_set_player_game_type.go
  • gobds/session/handler_sub_chunk.go
  • gobds/session/handler_text.go
  • gobds/session/handler_update_abilities.go
  • gobds/session/handler_update_player_game_type.go
  • gobds/session/session.go
  • gobds/session/traffic.go
  • gobds/session/traffic_test.go
  • gobds/session/util.go
  • gobds/session/util_claim_action.go
  • gobds/session/util_claim_action_test.go
  • gobds/user_config.go
  • policy/claim_policy.v1.json
**Actionable comments posted: 7** <details> <summary>🧹 Nitpick comments (5)</summary><blockquote> <details> <summary>gobds/session/handler_sub_chunk.go (1)</summary><blockquote> `71-79`: _🚀 Performance & Scalability_ | _🔵 Trivial_ | _⚡ Quick win_ **Hoist invariant dimension-range lookup out of the per-entry loop.** `dimensionRangeByID(pkt.Dimension, dimensions)` depends only on `pkt.Dimension`/`dimensions`, both constant for the whole packet, yet it's recomputed on every iteration of the `pkt.SubChunkEntries` loop. Move this (and the `rangeFound` check) above the loop. <details> <summary>♻️ Proposed fix</summary> ```diff + dimensionRange, rangeFound := dimensionRangeByID(pkt.Dimension, dimensions) entries := make([]protocol.SubChunkEntry, 0, len(pkt.SubChunkEntries)) for _, entry := range pkt.SubChunkEntries { ... - dimensionRange, rangeFound := dimensionRangeByID(pkt.Dimension, dimensions) // GoBDS disables the backend blob cache, ... if entry.Result != protocol.SubChunkResultSuccess || !rangeFound || !dimensionFound || ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/session/handler_sub_chunk.go` around lines 71 - 79, Move the invariant dimensionRangeByID lookup for pkt.Dimension and dimensions, including rangeFound, before the pkt.SubChunkEntries loop. Reuse those results in the per-entry condition while preserving the existing append-and-continue behavior for unsuccessful entries, missing dimensions or ranges, non-ready snapshots, and cache-enabled packets. ``` </details> <!-- cr-comment:v1:7f19c1183d66897d08b53b77 --> </blockquote></details> <details> <summary>gobds/claim/metrics.go (1)</summary><blockquote> `54-57`: _📐 Maintainability & Code Quality_ | _🔵 Trivial_ | _⚡ Quick win_ **Add doc comments to exported one-liner methods (lint failures).** CI flags `RefreshAttempt`, `RefreshSuccess`, `RefreshFailure`, `Packet`, and `Correction` as exported methods missing doc comments; the same applies to `SubchunkDecoded`/`SubchunkModified`/`SubchunkError` for consistency with the rest of the file's style. <details> <summary>📝 Proposed fix</summary> ```diff +// RefreshAttempt records one claim-refresh attempt. func (m *Metrics) RefreshAttempt() { m.refreshAttempts.Add(1) } +// RefreshSuccess records one successful claim refresh. func (m *Metrics) RefreshSuccess() { m.refreshSuccess.Add(1) } +// RefreshFailure records one failed claim refresh. func (m *Metrics) RefreshFailure() { m.refreshFailure.Add(1) } +// Packet records one processed packet. func (m *Metrics) Packet() { m.packets.Add(1) } ... +// Correction records whether a corrective packet was sent or skipped. func (m *Metrics) Correction(sent bool) { ``` </details> Also applies to: 106-106, 114-116 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/claim/metrics.go` around lines 54 - 57, Add Go doc comments for the exported Metrics methods RefreshAttempt, RefreshSuccess, RefreshFailure, Packet, Correction, SubchunkDecoded, SubchunkModified, and SubchunkError, briefly describing each method’s counter-increment behavior and starting each comment with the corresponding method name to satisfy lint. ``` </details> <!-- cr-comment:v1:61cbe4a93c601f78d982e3f6 --> _Source: Linters/SAST tools_ </blockquote></details> <details> <summary>gobds/session/traffic.go (1)</summary><blockquote> `73-130`: _📐 Maintainability & Code Quality_ | _🔵 Trivial_ | _⚡ Quick win_ **Reduce `WithDefaults` cyclomatic complexity to satisfy the lint gate.** The `gocyclo` check is failing on this function (complexity 19 > 15) due to the repeated `if x <= 0 { x = default }` pattern across 16 fields. <details> <summary>♻️ Suggested refactor using small default-filling helpers</summary> ```diff +func setDefaultRate(v *float64, def float64) { + if *v <= 0 { + *v = def + } +} + +func setDefaultBurst(v *int, def int) { + if *v <= 0 { + *v = def + } +} + func (c TrafficConfig) WithDefaults() TrafficConfig { defaults := DefaultTrafficConfig() - if c.Chat.Rate <= 0 { - c.Chat.Rate = defaults.Chat.Rate - } - if c.Chat.Burst <= 0 { - c.Chat.Burst = defaults.Chat.Burst - } - ... (repeat for every field) ... + setDefaultRate(&c.Chat.Rate, defaults.Chat.Rate) + setDefaultBurst(&c.Chat.Burst, defaults.Chat.Burst) + setDefaultRate(&c.Commands.Rate, defaults.Commands.Rate) + setDefaultBurst(&c.Commands.Burst, defaults.Commands.Burst) + setDefaultRate(&c.ModalFormResponses.Rate, defaults.ModalFormResponses.Rate) + setDefaultBurst(&c.ModalFormResponses.Burst, defaults.ModalFormResponses.Burst) + setDefaultRate(&c.InventoryTransactions.Rate, defaults.InventoryTransactions.Rate) + setDefaultBurst(&c.InventoryTransactions.Burst, defaults.InventoryTransactions.Burst) + setDefaultRate(&c.ItemStackRequests.Rate, defaults.ItemStackRequests.Rate) + setDefaultBurst(&c.ItemStackRequests.Burst, defaults.ItemStackRequests.Burst) + setDefaultBurst(&c.MaxTextBytes, defaults.MaxTextBytes) + setDefaultBurst(&c.MaxCommandBytes, defaults.MaxCommandBytes) + setDefaultBurst(&c.MaxFormResponseBytes, defaults.MaxFormResponseBytes) + setDefaultBurst(&c.MaxFormResponseValues, defaults.MaxFormResponseValues) + setDefaultBurst(&c.MaxInventoryActions, defaults.MaxInventoryActions) + setDefaultBurst(&c.MaxStackRequests, defaults.MaxStackRequests) + setDefaultBurst(&c.MaxStackActions, defaults.MaxStackActions) + setDefaultBurst(&c.MaxTotalStackActions, defaults.MaxTotalStackActions) return c } ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/session/traffic.go` around lines 73 - 130, Reduce the cyclomatic complexity of TrafficConfig.WithDefaults by extracting the repeated non-positive-value defaulting logic into small reusable helper functions, then use those helpers for the rate, burst, and limit fields. Preserve the existing DefaultTrafficConfig values and <= 0 replacement behavior for all fields. ``` </details> <!-- cr-comment:v1:a2c9fde1df01f2d5237e6b2b --> _Source: Linters/SAST tools_ </blockquote></details> <details> <summary>gobds/session/claim_policy_golden_test.go (1)</summary><blockquote> `62-85`: _📐 Maintainability & Code Quality_ | _🔵 Trivial_ | _⚡ Quick win_ **Fail loudly on unrecognized `action` values instead of silently defaulting.** `claimActionFromGolden` maps unknown strings to `ClaimAction(255)`, which isn't handled in `ClaimActionPermitted`'s switch and falls through to the default `return true`. A typo in a fixture's `action` field would silently pass unless the fixture also expects `permitted:false`. <details> <summary>♻️ Proposed fix</summary> ```diff -func claimActionFromGolden(value string) ClaimAction { +func claimActionFromGolden(t *testing.T, value string) ClaimAction { switch value { case "render": return ClaimActionRender @@ case "itemDrop": return ClaimActionItemDrop default: - return ClaimAction(255) + t.Fatalf("unknown golden action: %q", value) + return 0 } } ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/session/claim_policy_golden_test.go` around lines 62 - 85, Update claimActionFromGolden to fail loudly when given an unrecognized action string instead of returning ClaimAction(255). Use the test’s existing failure mechanism to report the invalid fixture value, while preserving all recognized action mappings and ensuring the function cannot silently produce a value that ClaimActionPermitted treats as permitted. ``` </details> <!-- cr-comment:v1:422e2347e941bd5a991570fd --> </blockquote></details> <details> <summary>gobds/claim/snapshot.go (1)</summary><blockquote> `54-59`: _🩺 Stability & Availability_ | _🔵 Trivial_ | _⚡ Quick win_ **`Candidates()` returns mutable pointers from an "immutable" snapshot.** The struct comment promises immutability and lock-free concurrent reads, but `Candidates` hands back `*PlayerClaim` pointers into the snapshot's own backing slice/cells map. Any downstream mutation through one of these pointers (accidental or otherwise) would corrupt state shared across concurrent sessions and across snapshot generations (the 304-revalidation path in `factory.go` reuses the same `claims`/`cells` backing data). Consider returning value copies, or making the contract explicit (doc comment + code review checklist) that callers must treat returned claims as read-only. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/claim/snapshot.go` around lines 54 - 59, Update Snapshot.Candidates to return independent PlayerClaim value copies rather than pointers into the snapshot’s cells backing data. Preserve nil and empty-result behavior, and adjust affected callers to consume the copied values while keeping Snapshot’s immutable, lock-free read contract intact. ``` </details> <!-- cr-comment:v1:8f9db6d295f40f6a4d5ba083 --> </blockquote></details> </blockquote></details> <details> <summary>🤖 Prompt for all review comments with AI agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Inline comments: In `@gobds/claim/service.go`: - Around line 33-113: Reduce FetchClaims complexity by extracting the HTTP response status handling into a dedicated helper, preserving the existing behavior for successful, not-modified, rate-limited, decode-failure, and unexpected-status responses. Have the helper manage response.Body closure and context cancellation and return the result, error, and retry decision so FetchClaims retains only request/retry orchestration. - Around line 86-90: Update the 200 OK handling in the fetch method so s.lastModified is only replaced when the response’s last-modified header is non-empty, matching the guard used in the 304 branch. Preserve the previously cached value for header-less responses while continuing to return it in FetchResult.LastModified. In `@gobds/session/handler_sub_chunk.go`: - Around line 20-99: Reduce cyclomatic complexity in SubChunkHandler.Handle by extracting snapshot and dimension resolution into a helper, and moving per-entry border and claim filtering into a separate helper. Keep Handle responsible for instrumentation, context validation, panic recovery, setup, and assigning the filtered entries, while preserving all existing filtering, metrics, and fail-open behavior. - Around line 111-156: Update applyClaimDenyBlocks to process every section in the visible dimension Y range instead of returning unless sectionY equals dimensionRange.Min(). For each denied x/z position, rewrite the corresponding blocks across all relevant local Y layers rather than hard-coding SetBlock’s y argument to 0, while preserving the existing claim checks, metrics, and payload handling. In `@gobds/session/handler_update_abilities.go`: - Around line 30-40: Update the refresh logic in the handler method containing SetOperator to call the shared correctiveLevelChunk helper instead of constructing packet.LevelChunk directly. Pass the current position as required by the helper so Dimension and HighestSubChunk are populated and the refresh targets the correct dimension. In `@gobds/session/session.go`: - Around line 444-447: Update Session.WriteTrafficMetrics so it does not pass the raw IdentityData().XUID to TrafficMetrics.WriteDelta; apply the project’s approved redaction, hashing, or truncation mechanism before emitting the session field, or require the established explicit configuration flag for raw identifiers if that is the supported policy. In `@gobds/session/util_claim_action.go`: - Around line 47-84: Reduce the cyclomatic complexity of ClaimActionPermitted below the gocyclo threshold by extracting per-action special-case logic, including admin-claim "*" handling for block interaction, entity interaction, and item drops, into small named helpers. Preserve all existing action outcomes and keep ClaimActionPermitted responsible for dispatching each ClaimAction to the appropriate helper. --- Nitpick comments: In `@gobds/claim/metrics.go`: - Around line 54-57: Add Go doc comments for the exported Metrics methods RefreshAttempt, RefreshSuccess, RefreshFailure, Packet, Correction, SubchunkDecoded, SubchunkModified, and SubchunkError, briefly describing each method’s counter-increment behavior and starting each comment with the corresponding method name to satisfy lint. In `@gobds/claim/snapshot.go`: - Around line 54-59: Update Snapshot.Candidates to return independent PlayerClaim value copies rather than pointers into the snapshot’s cells backing data. Preserve nil and empty-result behavior, and adjust affected callers to consume the copied values while keeping Snapshot’s immutable, lock-free read contract intact. In `@gobds/session/claim_policy_golden_test.go`: - Around line 62-85: Update claimActionFromGolden to fail loudly when given an unrecognized action string instead of returning ClaimAction(255). Use the test’s existing failure mechanism to report the invalid fixture value, while preserving all recognized action mappings and ensuring the function cannot silently produce a value that ClaimActionPermitted treats as permitted. In `@gobds/session/handler_sub_chunk.go`: - Around line 71-79: Move the invariant dimensionRangeByID lookup for pkt.Dimension and dimensions, including rangeFound, before the pkt.SubChunkEntries loop. Reuse those results in the per-entry condition while preserving the existing append-and-continue behavior for unsuccessful entries, missing dimensions or ranges, non-ready snapshots, and cache-enabled packets. In `@gobds/session/traffic.go`: - Around line 73-130: Reduce the cyclomatic complexity of TrafficConfig.WithDefaults by extracting the repeated non-positive-value defaulting logic into small reusable helper functions, then use those helpers for the rate, burst, and limit fields. Preserve the existing DefaultTrafficConfig values and <= 0 replacement behavior for all fields. ``` </details> <details> <summary>🪄 Autofix (Beta)</summary> Fix all unresolved CodeRabbit comments on this PR: - [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended) - [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes </details> --- <details> <summary>ℹ️ Review info</summary> <details> <summary>⚙️ Run configuration</summary> **Configuration used**: defaults **Review profile**: CHILL **Plan**: Pro **Run ID**: `b0887fe4-19e6-40eb-b4e4-450a3bd26ffb` </details> <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 8e4a5764e7127ec9903ba5ea017430a9c67ce5d0 and 5a9da191529ad93c7108fc9c71cadf42052ac3f3. </details> <details> <summary>📒 Files selected for processing (55)</summary> * `.github/workflows/lint.yml` * `.gitignore` * `config.example.toml` * `gobds/block/deny.go` * `gobds/block/factory.go` * `gobds/block/hash.go` * `gobds/claim/factory.go` * `gobds/claim/factory_test.go` * `gobds/claim/metrics.go` * `gobds/claim/metrics_test.go` * `gobds/claim/model.go` * `gobds/claim/model_test.go` * `gobds/claim/service.go` * `gobds/claim/service_test.go` * `gobds/claim/snapshot.go` * `gobds/claim/snapshot_test.go` * `gobds/config.go` * `gobds/config_test.go` * `gobds/entity/entity.go` * `gobds/entity/factory.go` * `gobds/entity/factory_test.go` * `gobds/gobds.go` * `gobds/server.go` * `gobds/server_test.go` * `gobds/service/authentication/service.go` * `gobds/service/vpn/service.go` * `gobds/session/claim_policy_golden_test.go` * `gobds/session/config.go` * `gobds/session/data.go` * `gobds/session/handler_add_actor.go` * `gobds/session/handler_add_painting.go` * `gobds/session/handler_change_dimension.go` * `gobds/session/handler_command_request.go` * `gobds/session/handler_inventory_transaction.go` * `gobds/session/handler_inventory_transaction_test.go` * `gobds/session/handler_item_registry.go` * `gobds/session/handler_item_stack_request.go` * `gobds/session/handler_modal_form_response.go` * `gobds/session/handler_move_actor.go` * `gobds/session/handler_player_auth_input.go` * `gobds/session/handler_player_auth_input_test.go` * `gobds/session/handler_remove_actor.go` * `gobds/session/handler_set_player_game_type.go` * `gobds/session/handler_sub_chunk.go` * `gobds/session/handler_text.go` * `gobds/session/handler_update_abilities.go` * `gobds/session/handler_update_player_game_type.go` * `gobds/session/session.go` * `gobds/session/traffic.go` * `gobds/session/traffic_test.go` * `gobds/session/util.go` * `gobds/session/util_claim_action.go` * `gobds/session/util_claim_action_test.go` * `gobds/user_config.go` * `policy/claim_policy.v1.json` </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
@ -15,6 +14,7 @@ import (
// Service ...
coderabbitai[bot] (Migrated from github.com) commented 2026-07-15 00:37:03 +00:00

🎯 Functional Correctness | 🟡 Minor | Quick win

200 OK path clears lastModified on a header-less response, unlike the 304 path.

Line 86 unconditionally overwrites s.lastModified with response.Header.Get("last-modified"), even when empty, dropping any previously cached value and disabling future If-Modified-Since revalidation until the server happens to send the header again. The 304 branch (lines 92-94) correctly guards this with if modified != "".

🩹 Proposed fix
-			s.lastModified = response.Header.Get("last-modified")
+			if modified := response.Header.Get("last-modified"); modified != "" {
+				s.lastModified = modified
+			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			if modified := response.Header.Get("last-modified"); modified != "" {
				s.lastModified = modified
			}
			return FetchResult{
				Claims:       obj,
				LastModified: s.lastModified,
			}, nil
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/claim/service.go` around lines 86 - 90, Update the 200 OK handling in
the fetch method so s.lastModified is only replaced when the response’s
last-modified header is non-empty, matching the guard used in the 304 branch.
Preserve the previously cached value for header-less responses while continuing
to return it in FetchResult.LastModified.

Addressed in commit cc0d3af

_🎯 Functional Correctness_ | _🟡 Minor_ | _⚡ Quick win_ **200 OK path clears `lastModified` on a header-less response, unlike the 304 path.** Line 86 unconditionally overwrites `s.lastModified` with `response.Header.Get("last-modified")`, even when empty, dropping any previously cached value and disabling future `If-Modified-Since` revalidation until the server happens to send the header again. The 304 branch (lines 92-94) correctly guards this with `if modified != ""`. <details> <summary>🩹 Proposed fix</summary> ```diff - s.lastModified = response.Header.Get("last-modified") + if modified := response.Header.Get("last-modified"); modified != "" { + s.lastModified = modified + } ``` </details> <!-- suggestion_start --> <details> <summary>📝 Committable suggestion</summary> > ‼️ **IMPORTANT** > Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements. ```suggestion if modified := response.Header.Get("last-modified"); modified != "" { s.lastModified = modified } return FetchResult{ Claims: obj, LastModified: s.lastModified, }, nil ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/claim/service.go` around lines 86 - 90, Update the 200 OK handling in the fetch method so s.lastModified is only replaced when the response’s last-modified header is non-empty, matching the guard used in the 304 branch. Preserve the previously cached value for header-less responses while continuing to return it in FetchResult.LastModified. ``` </details> <!-- fingerprinting:phantom:medusa:beignet --> <!-- cr-indicator-types:potential_issue --> <!-- cr-comment:v1:18d318335760f529be8c1c00 --> <!-- This is an auto-generated comment by CodeRabbit --> ✅ Addressed in commit cc0d3af
@ -86,0 +107,4 @@
LastModified: s.lastModified,
}, nil, false
case http.StatusNotModified:
if modified := response.Header.Get("last-modified"); modified != "" {
coderabbitai[bot] (Migrated from github.com) commented 2026-07-15 00:37:03 +00:00

📐 Maintainability & Code Quality | 🟠 Major | Quick win

FetchClaims exceeds the gocyclo complexity threshold (CI lint failure).

The lint check reports complexity 17 (> 15). Extracting the per-status-code handling (e.g. a helper that closes the body, cancels the context, and returns the appropriate (FetchResult, error, bool retry)) would bring this back under the threshold and improve readability without changing behavior.

🧰 Tools
🪛 GitHub Check: lint

[failure] 33-33:
cyclomatic complexity 17 of func (*Service).FetchClaims is high (> 15) (gocyclo)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/claim/service.go` around lines 33 - 113, Reduce FetchClaims complexity
by extracting the HTTP response status handling into a dedicated helper,
preserving the existing behavior for successful, not-modified, rate-limited,
decode-failure, and unexpected-status responses. Have the helper manage
response.Body closure and context cancellation and return the result, error, and
retry decision so FetchClaims retains only request/retry orchestration.

Source: Linters/SAST tools

Confirmed as addressed by @smell-of-curry

_📐 Maintainability & Code Quality_ | _🟠 Major_ | _⚡ Quick win_ **`FetchClaims` exceeds the gocyclo complexity threshold (CI lint failure).** The lint check reports complexity 17 (> 15). Extracting the per-status-code handling (e.g. a helper that closes the body, cancels the context, and returns the appropriate `(FetchResult, error, bool retry)`) would bring this back under the threshold and improve readability without changing behavior. <details> <summary>🧰 Tools</summary> <details> <summary>🪛 GitHub Check: lint</summary> [failure] 33-33: cyclomatic complexity 17 of func `(*Service).FetchClaims` is high (> 15) (gocyclo) </details> </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/claim/service.go` around lines 33 - 113, Reduce FetchClaims complexity by extracting the HTTP response status handling into a dedicated helper, preserving the existing behavior for successful, not-modified, rate-limited, decode-failure, and unexpected-status responses. Have the helper manage response.Body closure and context cancellation and return the result, error, and retry decision so FetchClaims retains only request/retry orchestration. ``` </details> <!-- fingerprinting:phantom:medusa:beignet --> <!-- cr-indicator-types:refactor_suggestion --> <!-- cr-comment:v1:2fc8a348ea49e5827968d36d --> _Source: Linters/SAST tools_ <!-- This is an auto-generated reply by CodeRabbit --> ✅ Confirmed as addressed by @smell-of-curry <!-- This is an auto-generated comment by CodeRabbit -->
@ -30,0 +128,4 @@
dimensionRange cube.Range,
claims []*claim.PlayerClaim,
denyID uint32,
actor ClaimActor,
coderabbitai[bot] (Migrated from github.com) commented 2026-07-15 00:37:03 +00:00

📐 Maintainability & Code Quality | 🟠 Major | Quick win

Reduce Handle's cyclomatic complexity (CI lint failure).

CI reports gocyclo complexity 18 (>15) for this function. It currently mixes latency instrumentation, panic-recovery setup, snapshot/dimension resolution, and per-entry border+claim filtering in one body. Consider extracting the snapshot/dimension resolution block (lines 39-53) and the per-entry filtering logic (lines 56-95) into separate helper functions to bring this under the threshold.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 57-57: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: int32(entry.Offset[0])
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)


[warning] 58-58: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: int32(entry.Offset[2])
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)

🪛 GitHub Check: lint

[failure] 20-20:
cyclomatic complexity 18 of func (*SubChunkHandler).Handle is high (> 15) (gocyclo)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/session/handler_sub_chunk.go` around lines 20 - 99, Reduce cyclomatic
complexity in SubChunkHandler.Handle by extracting snapshot and dimension
resolution into a helper, and moving per-entry border and claim filtering into a
separate helper. Keep Handle responsible for instrumentation, context
validation, panic recovery, setup, and assigning the filtered entries, while
preserving all existing filtering, metrics, and fail-open behavior.

Source: Linters/SAST tools

Addressed in commit cc0d3af

_📐 Maintainability & Code Quality_ | _🟠 Major_ | _⚡ Quick win_ **Reduce `Handle`'s cyclomatic complexity (CI lint failure).** CI reports `gocyclo` complexity 18 (>15) for this function. It currently mixes latency instrumentation, panic-recovery setup, snapshot/dimension resolution, and per-entry border+claim filtering in one body. Consider extracting the snapshot/dimension resolution block (lines 39-53) and the per-entry filtering logic (lines 56-95) into separate helper functions to bring this under the threshold. <details> <summary>🧰 Tools</summary> <details> <summary>🪛 ast-grep (0.44.1)</summary> [warning] 57-57: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values. Context: int32(entry.Offset[0]) Note: [CWE-190] Integer Overflow or Wraparound. (integer-overflow-narrowing-conversion-go) --- [warning] 58-58: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values. Context: int32(entry.Offset[2]) Note: [CWE-190] Integer Overflow or Wraparound. (integer-overflow-narrowing-conversion-go) </details> <details> <summary>🪛 GitHub Check: lint</summary> [failure] 20-20: cyclomatic complexity 18 of func `(*SubChunkHandler).Handle` is high (> 15) (gocyclo) </details> </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/session/handler_sub_chunk.go` around lines 20 - 99, Reduce cyclomatic complexity in SubChunkHandler.Handle by extracting snapshot and dimension resolution into a helper, and moving per-entry border and claim filtering into a separate helper. Keep Handle responsible for instrumentation, context validation, panic recovery, setup, and assigning the filtered entries, while preserving all existing filtering, metrics, and fail-open behavior. ``` </details> <!-- fingerprinting:phantom:medusa:beignet --> <!-- cr-indicator-types:refactor_suggestion --> <!-- cr-comment:v1:6fce89442e95bef6e7f71de9 --> _Source: Linters/SAST tools_ <!-- This is an auto-generated reply by CodeRabbit --> ✅ Addressed in commit cc0d3af
@ -30,0 +185,4 @@
chunk.EncodeSubChunk(virtualChunk, chunk.NetworkEncoding, int(index)),
blockEntityPayload...,
)
return entry
coderabbitai[bot] (Migrated from github.com) commented 2026-07-15 00:37:03 +00:00

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and related symbols.
git ls-files gobds/session/handler_sub_chunk.go
echo '--- outline ---'
ast-grep outline gobds/session/handler_sub_chunk.go --view expanded || true
echo '--- search symbols ---'
rg -n "applyClaimDenyBlocks|decodeSubChunk|SetBlock\(" gobds/session/handler_sub_chunk.go gobds/session -S || true
echo '--- file excerpt ---'
nl -ba gobds/session/handler_sub_chunk.go | sed -n '1,260p'

Repository: smell-of-curry/gobds

Length of output: 2114


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- function slice ---'
sed -n '70,180p' gobds/session/handler_sub_chunk.go

echo '--- SetBlock/SubChunk searches ---'
rg -n "SetBlock\([^)]*0, z, 0|SetBlock\(|type SubChunk|func .*SubChunk" gobds -S || true

Repository: smell-of-curry/gobds

Length of output: 3898


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target function and nearby call path.
python3 - <<'PY'
from pathlib import Path
p = Path("gobds/session/handler_sub_chunk.go")
text = p.read_text()
lines = text.splitlines()
for start, end in [(70, 180)]:
    print(f"--- {p} lines {start}-{end} ---")
    for i in range(start, min(end, len(lines)) + 1):
        print(f"{i:4}: {lines[i-1]}")
PY

echo '--- SetBlock/SubChunk searches ---'
rg -n "SetBlock\(|type SubChunk|func .*SubChunk|decodeSubChunk" gobds -S || true

Repository: smell-of-curry/gobds

Length of output: 4915


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the function with line numbers without relying on nl.
python3 - <<'PY'
from pathlib import Path
p = Path("gobds/session/handler_sub_chunk.go")
for i, line in enumerate(p.read_text().splitlines(), 1):
    if 70 <= i <= 180:
        print(f"{i:4}: {line}")
PY

Repository: smell-of-curry/gobds

Length of output: 4029


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path("gobds/session/handler_sub_chunk.go")
lines = p.read_text().splitlines()
for start, end in [(70, 180)]:
    print(f"--- {p} lines {start}-{end} ---")
    for i in range(start, min(end, len(lines)) + 1):
        print(f"{i:4}: {lines[i-1]}")
PY

echo '--- repository searches ---'
rg -n "SetBlock\(|decodeSubChunk|type SubChunk|func .*SubChunk" gobds -S || true

Repository: smell-of-curry/gobds

Length of output: 4908


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "claim deny|deny render|applyClaimDenyBlocks|SubChunkHandler|render.*claim|singleClaimAt|ClaimActionRender" gobds -S || true

Repository: smell-of-curry/gobds

Length of output: 2024


applyClaimDenyBlocks only rewrites the bottom-most layer. sectionY limits this to the dimension’s minimum section, and SetBlock(x, 0, z, 0, denyID) hard-codes y=0, so this affects just one 16×16 slice at the world floor. If the goal is to hide claimed areas, this needs to cover the full visible Y range, not a single slice.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 111-111: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: int32(dimensionRange.Min()>>4)
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)


[warning] 139-139: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: int32(x)
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)


[warning] 139-139: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: int32(z)
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)


[warning] 148-148: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: uint8(ClaimActionRender)
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/session/handler_sub_chunk.go` around lines 111 - 156, Update
applyClaimDenyBlocks to process every section in the visible dimension Y range
instead of returning unless sectionY equals dimensionRange.Min(). For each
denied x/z position, rewrite the corresponding blocks across all relevant local
Y layers rather than hard-coding SetBlock’s y argument to 0, while preserving
the existing claim checks, metrics, and payload handling.

Addressed in commit cc0d3af

_🎯 Functional Correctness_ | _🟠 Major_ | _🏗️ Heavy lift_ <details> <summary>🧩 Analysis chain</summary> 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Map the target file and related symbols. git ls-files gobds/session/handler_sub_chunk.go echo '--- outline ---' ast-grep outline gobds/session/handler_sub_chunk.go --view expanded || true echo '--- search symbols ---' rg -n "applyClaimDenyBlocks|decodeSubChunk|SetBlock\(" gobds/session/handler_sub_chunk.go gobds/session -S || true echo '--- file excerpt ---' nl -ba gobds/session/handler_sub_chunk.go | sed -n '1,260p' ``` Repository: smell-of-curry/gobds Length of output: 2114 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail echo '--- function slice ---' sed -n '70,180p' gobds/session/handler_sub_chunk.go echo '--- SetBlock/SubChunk searches ---' rg -n "SetBlock\([^)]*0, z, 0|SetBlock\(|type SubChunk|func .*SubChunk" gobds -S || true ``` Repository: smell-of-curry/gobds Length of output: 3898 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Inspect the target function and nearby call path. python3 - <<'PY' from pathlib import Path p = Path("gobds/session/handler_sub_chunk.go") text = p.read_text() lines = text.splitlines() for start, end in [(70, 180)]: print(f"--- {p} lines {start}-{end} ---") for i in range(start, min(end, len(lines)) + 1): print(f"{i:4}: {lines[i-1]}") PY echo '--- SetBlock/SubChunk searches ---' rg -n "SetBlock\(|type SubChunk|func .*SubChunk|decodeSubChunk" gobds -S || true ``` Repository: smell-of-curry/gobds Length of output: 4915 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Read the function with line numbers without relying on nl. python3 - <<'PY' from pathlib import Path p = Path("gobds/session/handler_sub_chunk.go") for i, line in enumerate(p.read_text().splitlines(), 1): if 70 <= i <= 180: print(f"{i:4}: {line}") PY ``` Repository: smell-of-curry/gobds Length of output: 4029 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail python3 - <<'PY' from pathlib import Path p = Path("gobds/session/handler_sub_chunk.go") lines = p.read_text().splitlines() for start, end in [(70, 180)]: print(f"--- {p} lines {start}-{end} ---") for i in range(start, min(end, len(lines)) + 1): print(f"{i:4}: {lines[i-1]}") PY echo '--- repository searches ---' rg -n "SetBlock\(|decodeSubChunk|type SubChunk|func .*SubChunk" gobds -S || true ``` Repository: smell-of-curry/gobds Length of output: 4908 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail rg -n "claim deny|deny render|applyClaimDenyBlocks|SubChunkHandler|render.*claim|singleClaimAt|ClaimActionRender" gobds -S || true ``` Repository: smell-of-curry/gobds Length of output: 2024 --- </details> **`applyClaimDenyBlocks` only rewrites the bottom-most layer.** `sectionY` limits this to the dimension’s minimum section, and `SetBlock(x, 0, z, 0, denyID)` hard-codes `y=0`, so this affects just one 16×16 slice at the world floor. If the goal is to hide claimed areas, this needs to cover the full visible Y range, not a single slice. <details> <summary>🧰 Tools</summary> <details> <summary>🪛 ast-grep (0.44.1)</summary> [warning] 111-111: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values. Context: int32(dimensionRange.Min()>>4) Note: [CWE-190] Integer Overflow or Wraparound. (integer-overflow-narrowing-conversion-go) --- [warning] 139-139: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values. Context: int32(x) Note: [CWE-190] Integer Overflow or Wraparound. (integer-overflow-narrowing-conversion-go) --- [warning] 139-139: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values. Context: int32(z) Note: [CWE-190] Integer Overflow or Wraparound. (integer-overflow-narrowing-conversion-go) --- [warning] 148-148: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values. Context: uint8(ClaimActionRender) Note: [CWE-190] Integer Overflow or Wraparound. (integer-overflow-narrowing-conversion-go) </details> </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/session/handler_sub_chunk.go` around lines 111 - 156, Update applyClaimDenyBlocks to process every section in the visible dimension Y range instead of returning unless sectionY equals dimensionRange.Min(). For each denied x/z position, rewrite the corresponding blocks across all relevant local Y layers rather than hard-coding SetBlock’s y argument to 0, while preserving the existing claim checks, metrics, and payload handling. ``` </details> <!-- fingerprinting:phantom:medusa:beignet --> <!-- cr-indicator-types:potential_issue --> <!-- cr-comment:v1:fdb43fe30f8cffd183fa7d35 --> <!-- This is an auto-generated reply by CodeRabbit --> ✅ Addressed in commit cc0d3af
@ -0,0 +39,4 @@
}
s.WriteToClient(correction)
return nil
}
coderabbitai[bot] (Migrated from github.com) commented 2026-07-15 00:37:03 +00:00

🎯 Functional Correctness | 🟡 Minor | Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the relevant handler and the shared corrective chunk helper.
rg -n "correctiveLevelChunk|LevelChunk\\{|SetOperator\\(|SubChunkRequestModeLimited|HighestSubChunk|Dimension" gobds/session -S

# Show the two relevant files with line numbers if they exist.
for f in \
  gobds/session/handler_update_abilities.go \
  gobds/session/handler_player_auth_input.go
do
  if [ -f "$f" ]; then
    echo "===== $f ====="
    cat -n "$f" | sed -n '1,240p'
  fi
done

Repository: smell-of-curry/gobds

Length of output: 10869


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the packet definition and protocol types referenced by the handlers.
rg -n "type LevelChunk|type ChunkPos|SubChunkRequestModeLimited|HighestSubChunk|Dimension" . -S

Repository: smell-of-curry/gobds

Length of output: 5929


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the corrective helper and packet type definitions with enough context to inspect defaults/semantics.
for f in \
  gobds/session/handler_player_auth_input.go \
  gobds/session/handler_update_abilities.go
do
  if [ -f "$f" ]; then
    echo "===== $f ====="
    sed -n '1,220p' "$f" | cat -n
  fi
done

# Locate the packet definition if it is vendored or in a local module cache path exposed in the repo.
rg -n "type LevelChunk struct|HighestSubChunk|SubChunkRequestModeLimited|Dimension" . -S

Repository: smell-of-curry/gobds

Length of output: 11673


Reuse correctiveLevelChunk for this refresh. This packet leaves Dimension and HighestSubChunk unset, so the forced chunk refresh can target the wrong dimension outside the Overworld. Reuse the shared helper here instead of building packet.LevelChunk manually.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 33-33: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: int32(math.Floor(float64(position.X())))
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)


[warning] 34-34: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: int32(math.Floor(float64(position.Z())))
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/session/handler_update_abilities.go` around lines 30 - 40, Update the
refresh logic in the handler method containing SetOperator to call the shared
correctiveLevelChunk helper instead of constructing packet.LevelChunk directly.
Pass the current position as required by the helper so Dimension and
HighestSubChunk are populated and the refresh targets the correct dimension.

Addressed in commit cc0d3af

_🎯 Functional Correctness_ | _🟡 Minor_ | _⚡ Quick win_ <details> <summary>🧩 Analysis chain</summary> 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Locate the relevant handler and the shared corrective chunk helper. rg -n "correctiveLevelChunk|LevelChunk\\{|SetOperator\\(|SubChunkRequestModeLimited|HighestSubChunk|Dimension" gobds/session -S # Show the two relevant files with line numbers if they exist. for f in \ gobds/session/handler_update_abilities.go \ gobds/session/handler_player_auth_input.go do if [ -f "$f" ]; then echo "===== $f =====" cat -n "$f" | sed -n '1,240p' fi done ``` Repository: smell-of-curry/gobds Length of output: 10869 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Inspect the packet definition and protocol types referenced by the handlers. rg -n "type LevelChunk|type ChunkPos|SubChunkRequestModeLimited|HighestSubChunk|Dimension" . -S ``` Repository: smell-of-curry/gobds Length of output: 5929 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Show the corrective helper and packet type definitions with enough context to inspect defaults/semantics. for f in \ gobds/session/handler_player_auth_input.go \ gobds/session/handler_update_abilities.go do if [ -f "$f" ]; then echo "===== $f =====" sed -n '1,220p' "$f" | cat -n fi done # Locate the packet definition if it is vendored or in a local module cache path exposed in the repo. rg -n "type LevelChunk struct|HighestSubChunk|SubChunkRequestModeLimited|Dimension" . -S ``` Repository: smell-of-curry/gobds Length of output: 11673 --- </details> **Reuse `correctiveLevelChunk` for this refresh.** This packet leaves `Dimension` and `HighestSubChunk` unset, so the forced chunk refresh can target the wrong dimension outside the Overworld. Reuse the shared helper here instead of building `packet.LevelChunk` manually. <details> <summary>🧰 Tools</summary> <details> <summary>🪛 ast-grep (0.44.1)</summary> [warning] 33-33: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values. Context: int32(math.Floor(float64(position.X()))) Note: [CWE-190] Integer Overflow or Wraparound. (integer-overflow-narrowing-conversion-go) --- [warning] 34-34: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values. Context: int32(math.Floor(float64(position.Z()))) Note: [CWE-190] Integer Overflow or Wraparound. (integer-overflow-narrowing-conversion-go) </details> </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/session/handler_update_abilities.go` around lines 30 - 40, Update the refresh logic in the handler method containing SetOperator to call the shared correctiveLevelChunk helper instead of constructing packet.LevelChunk directly. Pass the current position as required by the helper so Dimension and HighestSubChunk are populated and the refresh targets the correct dimension. ``` </details> <!-- fingerprinting:phantom:medusa:beignet --> <!-- cr-indicator-types:potential_issue --> <!-- cr-comment:v1:c6182ea9421ebc52d431cbc2 --> <!-- This is an auto-generated comment by CodeRabbit --> ✅ Addressed in commit cc0d3af
coderabbitai[bot] (Migrated from github.com) commented 2026-07-15 00:37:03 +00:00

🔒 Security & Privacy | 🟠 Major | Quick win

Raw XUID persisted into traffic metrics output.

WriteTrafficMetrics passes s.IdentityData().XUID into TrafficMetrics.WriteDelta, which JSON-serializes it as the session field of every emitted traffic_protection_metrics record. This writes a persistent per-player identifier into metrics/log output, which may need redaction, hashing, or an explicit retention policy depending on compliance requirements (XUID can be used to identify/correlate an individual player over time).

Consider hashing/truncating the XUID before logging, or gating raw-XUID inclusion behind an explicit config flag if it's needed for abuse investigation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/session/session.go` around lines 444 - 447, Update
Session.WriteTrafficMetrics so it does not pass the raw IdentityData().XUID to
TrafficMetrics.WriteDelta; apply the project’s approved redaction, hashing, or
truncation mechanism before emitting the session field, or require the
established explicit configuration flag for raw identifiers if that is the
supported policy.
_🔒 Security & Privacy_ | _🟠 Major_ | _⚡ Quick win_ **Raw XUID persisted into traffic metrics output.** `WriteTrafficMetrics` passes `s.IdentityData().XUID` into `TrafficMetrics.WriteDelta`, which JSON-serializes it as the `session` field of every emitted `traffic_protection_metrics` record. This writes a persistent per-player identifier into metrics/log output, which may need redaction, hashing, or an explicit retention policy depending on compliance requirements (XUID can be used to identify/correlate an individual player over time). Consider hashing/truncating the XUID before logging, or gating raw-XUID inclusion behind an explicit config flag if it's needed for abuse investigation. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/session/session.go` around lines 444 - 447, Update Session.WriteTrafficMetrics so it does not pass the raw IdentityData().XUID to TrafficMetrics.WriteDelta; apply the project’s approved redaction, hashing, or truncation mechanism before emitting the session field, or require the established explicit configuration flag for raw identifiers if that is the supported policy. ``` </details> <!-- fingerprinting:phantom:medusa:beignet --> <!-- cr-indicator-types:potential_issue --> <!-- cr-comment:v1:c4707ec4359477cfb585c277 --> <!-- This is an auto-generated reply by CodeRabbit -->
@ -0,0 +72,4 @@
return claimActionItemDropPermitted(cl, data)
}
return true
}
coderabbitai[bot] (Migrated from github.com) commented 2026-07-15 00:37:03 +00:00

📐 Maintainability & Code Quality | 🟠 Major | Quick win

Fix the failing lint check: ClaimActionPermitted cyclomatic complexity is 16 (> 15).

The GitHub Check: lint pipeline reports this function over the gocyclo threshold. Extracting the per-action special-case branches (e.g. the admin-claim "*" handling for block-interact/entity-interact/item-drop) into small named helpers would reduce complexity without changing behavior.

♻️ Proposed refactor sketch
 	switch action {
 	case ClaimActionRender:
 		return handleClaimActionRender(cl, data)
 	case ClaimActionBlockBreak:
 		return handleClaimActionInFeature(cl, data, claim.FeatureTypeMineable)
 	case ClaimActionBlockPlace:
 		return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockPlaceable)
 	case ClaimActionBlockInteract:
-		if cl.OwnerXUID == "*" && adminClaimBlockInteractionAllowed(data) {
-			return true
-		}
-		return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockInteractable)
+		return claimActionBlockInteractPermitted(cl, data)
 	case ClaimActionEntityInteract:
-		if cl.OwnerXUID == "*" {
-			return true
-		}
-		return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityInteractable)
+		return claimActionEntityInteractPermitted(cl, data)
 	case ClaimActionEntityHurt:
 		return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityHurt)
 	case ClaimActionItemRelease, ClaimActionItemThrow:
 		return true
 	case ClaimActionItemDrop:
-		if cl.OwnerXUID == "*" {
-			return true
-		}
-		return handleClaimActionInFeature(cl, data, claim.FeatureTypeDropItems)
+		return claimActionItemDropPermitted(cl, data)
 	}
 	return true
+}
+
+func claimActionBlockInteractPermitted(cl claim.PlayerClaim, data any) bool {
+	if cl.OwnerXUID == "*" && adminClaimBlockInteractionAllowed(data) {
+		return true
+	}
+	return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockInteractable)
+}
+
+func claimActionEntityInteractPermitted(cl claim.PlayerClaim, data any) bool {
+	if cl.OwnerXUID == "*" {
+		return true
+	}
+	return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityInteractable)
+}
+
+func claimActionItemDropPermitted(cl claim.PlayerClaim, data any) bool {
+	if cl.OwnerXUID == "*" {
+		return true
+	}
+	return handleClaimActionInFeature(cl, data, claim.FeatureTypeDropItems)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

func ClaimActionPermitted(cl claim.PlayerClaim, actor ClaimActor, action ClaimAction, data any) bool {
	if !validClaim(cl) || actor.XUID == "" {
		return true
	}
	if claimOwnerOrTrusted(cl, actor) {
		return true
	}
	switch action {
	case ClaimActionRender:
		return handleClaimActionRender(cl, data)
	case ClaimActionBlockBreak:
		return handleClaimActionInFeature(cl, data, claim.FeatureTypeMineable)
	case ClaimActionBlockPlace:
		return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockPlaceable)
	case ClaimActionBlockInteract:
		return claimActionBlockInteractPermitted(cl, data)
	case ClaimActionEntityInteract:
		return claimActionEntityInteractPermitted(cl, data)
	case ClaimActionEntityHurt:
		return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityHurt)
	case ClaimActionItemRelease, ClaimActionItemThrow:
		// ReleaseItem stops item use (food, bows, fishing), while click-air
		// throwables are not item drops. BEH does not claim-filter either.
		return true
	case ClaimActionItemDrop:
		return claimActionItemDropPermitted(cl, data)
	}
	return true
}

func claimActionBlockInteractPermitted(cl claim.PlayerClaim, data any) bool {
	if cl.OwnerXUID == "*" && adminClaimBlockInteractionAllowed(data) {
		return true
	}
	return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockInteractable)
}

func claimActionEntityInteractPermitted(cl claim.PlayerClaim, data any) bool {
	if cl.OwnerXUID == "*" {
		return true
	}
	return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityInteractable)
}

func claimActionItemDropPermitted(cl claim.PlayerClaim, data any) bool {
	if cl.OwnerXUID == "*" {
		return true
	}
	return handleClaimActionInFeature(cl, data, claim.FeatureTypeDropItems)
}
🧰 Tools
🪛 GitHub Check: lint

[failure] 47-47:
cyclomatic complexity 16 of func ClaimActionPermitted is high (> 15) (gocyclo)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gobds/session/util_claim_action.go` around lines 47 - 84, Reduce the
cyclomatic complexity of ClaimActionPermitted below the gocyclo threshold by
extracting per-action special-case logic, including admin-claim "*" handling for
block interaction, entity interaction, and item drops, into small named helpers.
Preserve all existing action outcomes and keep ClaimActionPermitted responsible
for dispatching each ClaimAction to the appropriate helper.

Source: Pipeline failures

Addressed in commit cc0d3af

_📐 Maintainability & Code Quality_ | _🟠 Major_ | _⚡ Quick win_ **Fix the failing lint check: `ClaimActionPermitted` cyclomatic complexity is 16 (> 15).** The `GitHub Check: lint` pipeline reports this function over the gocyclo threshold. Extracting the per-action special-case branches (e.g. the admin-claim `"*"` handling for block-interact/entity-interact/item-drop) into small named helpers would reduce complexity without changing behavior. <details> <summary>♻️ Proposed refactor sketch</summary> ```diff switch action { case ClaimActionRender: return handleClaimActionRender(cl, data) case ClaimActionBlockBreak: return handleClaimActionInFeature(cl, data, claim.FeatureTypeMineable) case ClaimActionBlockPlace: return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockPlaceable) case ClaimActionBlockInteract: - if cl.OwnerXUID == "*" && adminClaimBlockInteractionAllowed(data) { - return true - } - return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockInteractable) + return claimActionBlockInteractPermitted(cl, data) case ClaimActionEntityInteract: - if cl.OwnerXUID == "*" { - return true - } - return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityInteractable) + return claimActionEntityInteractPermitted(cl, data) case ClaimActionEntityHurt: return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityHurt) case ClaimActionItemRelease, ClaimActionItemThrow: return true case ClaimActionItemDrop: - if cl.OwnerXUID == "*" { - return true - } - return handleClaimActionInFeature(cl, data, claim.FeatureTypeDropItems) + return claimActionItemDropPermitted(cl, data) } return true +} + +func claimActionBlockInteractPermitted(cl claim.PlayerClaim, data any) bool { + if cl.OwnerXUID == "*" && adminClaimBlockInteractionAllowed(data) { + return true + } + return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockInteractable) +} + +func claimActionEntityInteractPermitted(cl claim.PlayerClaim, data any) bool { + if cl.OwnerXUID == "*" { + return true + } + return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityInteractable) +} + +func claimActionItemDropPermitted(cl claim.PlayerClaim, data any) bool { + if cl.OwnerXUID == "*" { + return true + } + return handleClaimActionInFeature(cl, data, claim.FeatureTypeDropItems) } ``` </details> <!-- suggestion_start --> <details> <summary>📝 Committable suggestion</summary> > ‼️ **IMPORTANT** > Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements. ```suggestion func ClaimActionPermitted(cl claim.PlayerClaim, actor ClaimActor, action ClaimAction, data any) bool { if !validClaim(cl) || actor.XUID == "" { return true } if claimOwnerOrTrusted(cl, actor) { return true } switch action { case ClaimActionRender: return handleClaimActionRender(cl, data) case ClaimActionBlockBreak: return handleClaimActionInFeature(cl, data, claim.FeatureTypeMineable) case ClaimActionBlockPlace: return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockPlaceable) case ClaimActionBlockInteract: return claimActionBlockInteractPermitted(cl, data) case ClaimActionEntityInteract: return claimActionEntityInteractPermitted(cl, data) case ClaimActionEntityHurt: return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityHurt) case ClaimActionItemRelease, ClaimActionItemThrow: // ReleaseItem stops item use (food, bows, fishing), while click-air // throwables are not item drops. BEH does not claim-filter either. return true case ClaimActionItemDrop: return claimActionItemDropPermitted(cl, data) } return true } func claimActionBlockInteractPermitted(cl claim.PlayerClaim, data any) bool { if cl.OwnerXUID == "*" && adminClaimBlockInteractionAllowed(data) { return true } return handleClaimActionInFeature(cl, data, claim.FeatureTypeBlockInteractable) } func claimActionEntityInteractPermitted(cl claim.PlayerClaim, data any) bool { if cl.OwnerXUID == "*" { return true } return handleClaimActionInFeature(cl, data, claim.FeatureTypeEntityInteractable) } func claimActionItemDropPermitted(cl claim.PlayerClaim, data any) bool { if cl.OwnerXUID == "*" { return true } return handleClaimActionInFeature(cl, data, claim.FeatureTypeDropItems) } ``` </details> <!-- suggestion_end --> <details> <summary>🧰 Tools</summary> <details> <summary>🪛 GitHub Check: lint</summary> [failure] 47-47: cyclomatic complexity 16 of func `ClaimActionPermitted` is high (> 15) (gocyclo) </details> </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gobds/session/util_claim_action.go` around lines 47 - 84, Reduce the cyclomatic complexity of ClaimActionPermitted below the gocyclo threshold by extracting per-action special-case logic, including admin-claim "*" handling for block interaction, entity interaction, and item drops, into small named helpers. Preserve all existing action outcomes and keep ClaimActionPermitted responsible for dispatching each ClaimAction to the appropriate helper. ``` </details> <!-- fingerprinting:phantom:medusa:beignet --> <!-- cr-indicator-types:potential_issue --> <!-- cr-comment:v1:0220ba20b1bdee28d526e4b0 --> _Source: Pipeline failures_ <!-- This is an auto-generated comment by CodeRabbit --> ✅ Addressed in commit cc0d3af
smell-of-curry (Migrated from github.com) reviewed 2026-07-16 15:22:29 +00:00
@ -86,0 +107,4 @@
LastModified: s.lastModified,
}, nil, false
case http.StatusNotModified:
if modified := response.Header.Get("last-modified"); modified != "" {
smell-of-curry (Migrated from github.com) commented 2026-07-16 15:22:29 +00:00

Fixed in cc0d3af — extracted handleFetchResponse so FetchClaims stays under the gocyclo threshold.

Fixed in cc0d3af — extracted `handleFetchResponse` so `FetchClaims` stays under the gocyclo threshold.
smell-of-curry (Migrated from github.com) reviewed 2026-07-16 15:22:30 +00:00
@ -15,6 +14,7 @@ import (
// Service ...
smell-of-curry (Migrated from github.com) commented 2026-07-16 15:22:30 +00:00

Fixed in cc0d3af — 200 OK now only updates lastModified when the header is non-empty, matching the 304 path.

Fixed in cc0d3af — 200 OK now only updates `lastModified` when the header is non-empty, matching the 304 path.
smell-of-curry (Migrated from github.com) reviewed 2026-07-16 15:22:31 +00:00
@ -30,0 +128,4 @@
dimensionRange cube.Range,
claims []*claim.PlayerClaim,
denyID uint32,
actor ClaimActor,
smell-of-curry (Migrated from github.com) commented 2026-07-16 15:22:31 +00:00

Fixed in cc0d3af — snapshot/dimension setup and per-entry filtering extracted; dimensionRangeByID hoisted above the loop.

Fixed in cc0d3af — snapshot/dimension setup and per-entry filtering extracted; `dimensionRangeByID` hoisted above the loop.
smell-of-curry (Migrated from github.com) reviewed 2026-07-16 15:22:33 +00:00
@ -30,0 +185,4 @@
chunk.EncodeSubChunk(virtualChunk, chunk.NetworkEncoding, int(index)),
blockEntityPayload...,
)
return entry
smell-of-curry (Migrated from github.com) commented 2026-07-16 15:22:33 +00:00

Intentional — deny rendering places a floor marker at the dimension min section (y=0 only). Full-Y rewrite would change player-visible claim rendering and cost decode/modify on every subchunk; keeping floor-only.

Intentional — deny rendering places a floor marker at the dimension min section (`y=0` only). Full-Y rewrite would change player-visible claim rendering and cost decode/modify on every subchunk; keeping floor-only.
smell-of-curry (Migrated from github.com) reviewed 2026-07-16 15:22:34 +00:00
@ -0,0 +39,4 @@
}
s.WriteToClient(correction)
return nil
}
smell-of-curry (Migrated from github.com) commented 2026-07-16 15:22:34 +00:00

Fixed in cc0d3af — operator refresh now uses correctiveLevelChunk so Dimension and HighestSubChunk are populated.

Fixed in cc0d3af — operator refresh now uses `correctiveLevelChunk` so `Dimension` and `HighestSubChunk` are populated.
smell-of-curry (Migrated from github.com) reviewed 2026-07-16 15:22:35 +00:00
smell-of-curry (Migrated from github.com) commented 2026-07-16 15:22:35 +00:00

Keeping raw XUID — traffic metrics are operational abuse telemetry keyed by session; hashing would break correlating rate-limit spikes to a player. Same ops model as claim proxy counters.

Keeping raw XUID — traffic metrics are operational abuse telemetry keyed by session; hashing would break correlating rate-limit spikes to a player. Same ops model as claim proxy counters.
smell-of-curry (Migrated from github.com) reviewed 2026-07-16 15:22:36 +00:00
@ -0,0 +72,4 @@
return claimActionItemDropPermitted(cl, data)
}
return true
}
smell-of-curry (Migrated from github.com) commented 2026-07-16 15:22:36 +00:00

Fixed in cc0d3af — extracted claimActionBlockInteractPermitted / EntityInteract / ItemDrop helpers.

Fixed in cc0d3af — extracted `claimActionBlockInteractPermitted` / `EntityInteract` / `ItemDrop` helpers.
coderabbitai[bot] (Migrated from github.com) reviewed 2026-07-16 15:22:47 +00:00
@ -86,0 +107,4 @@
LastModified: s.lastModified,
}, nil, false
case http.StatusNotModified:
if modified := response.Header.Get("last-modified"); modified != "" {
coderabbitai[bot] (Migrated from github.com) commented 2026-07-16 15:22:46 +00:00

@smell-of-curry, thanks — the extracted handleFetchResponse keeps FetchClaims focused on retry orchestration and addresses the gocyclo finding. 🐇


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

`@smell-of-curry`, thanks — the extracted `handleFetchResponse` keeps `FetchClaims` focused on retry orchestration and addresses the gocyclo finding. 🐇 <!-- <review_comment_addressed> --> --- <!-- This is an auto-generated comment: tweet message by coderabbit.ai --> If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=CodeRabbit%20caught%20FetchClaims%20at%20complexity%2017%20and%20suggested%20extracting%20response%20handling%20to%20pass%20CI%2C%20preserve%20behavior%2C%20and%20improve%20readability.%20Try%20%40coderabbitai%20%F0%9F%9A%80&url=https%3A%2F%2Fgithub.com%2Fsmell-of-curry%2Fgobds%2Fpull%2F81%23discussion_r3583625029)? Thank you for using CodeRabbit! <!-- end of auto-generated comment: tweet message by coderabbit.ai --> <!-- This is an auto-generated reply by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) reviewed 2026-07-16 15:22:48 +00:00
@ -15,6 +14,7 @@ import (
// Service ...
coderabbitai[bot] (Migrated from github.com) commented 2026-07-16 15:22:48 +00:00

@smell-of-curry, confirmed—the guarded update preserves the cached validator on header-less 200 OK responses, consistent with the 304 Not Modified path. Thanks!


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

`@smell-of-curry`, confirmed—the guarded update preserves the cached validator on header-less `200 OK` responses, consistent with the `304 Not Modified` path. Thanks! <!-- <review_comment_addressed> --> --- <!-- This is an auto-generated comment: tweet message by coderabbit.ai --> If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=%40coderabbitai%20caught%20a%20subtle%20cache%20bug%3A%20200%20responses%20without%20%60Last-Modified%60%20were%20clearing%20revalidation%20state.%20Guarding%20empty%20headers%20preserves%20%60If-Modified-Since%60%20caching.%20Try%20it!%20%F0%9F%90%87%F0%9F%94%A7&url=https%3A%2F%2Fgithub.com%2Fsmell-of-curry%2Fgobds%2Fpull%2F81%23discussion_r3583625035)? Thank you for using CodeRabbit! <!-- end of auto-generated comment: tweet message by coderabbit.ai --> <!-- This is an auto-generated reply by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) reviewed 2026-07-16 15:22:52 +00:00
@ -0,0 +39,4 @@
}
s.WriteToClient(correction)
return nil
}
coderabbitai[bot] (Migrated from github.com) commented 2026-07-16 15:22:52 +00:00

@smell-of-curry, thanks for addressing this. Reusing correctiveLevelChunk ensures the operator-change refresh carries the correct dimension metadata and subchunk range.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

`@smell-of-curry`, thanks for addressing this. Reusing `correctiveLevelChunk` ensures the operator-change refresh carries the correct dimension metadata and subchunk range. <!-- <review_comment_addressed> --> --- <!-- This is an auto-generated comment: tweet message by coderabbit.ai --> If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=Great%20catch%20by%20%40coderabbitai%3A%20reusing%20%60correctiveLevelChunk%60%20populates%20Dimension%20and%20HighestSubChunk%2C%20ensuring%20operator%20refreshes%20target%20the%20right%20dimension.%20Try%20it%20for%20safer%20reviews!%20%F0%9F%8E%AF&url=https%3A%2F%2Fgithub.com%2Fsmell-of-curry%2Fgobds%2Fpull%2F81%23discussion_r3583625054)? Thank you for using CodeRabbit! <!-- end of auto-generated comment: tweet message by coderabbit.ai --> <!-- This is an auto-generated reply by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) reviewed 2026-07-16 15:22:52 +00:00
@ -0,0 +72,4 @@
return claimActionItemDropPermitted(cl, data)
}
return true
}
coderabbitai[bot] (Migrated from github.com) commented 2026-07-16 15:22:52 +00:00

@smell-of-curry, thanks—those helper extractions address the complexity finding and keep the policy dispatch clear. 🐇


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

`@smell-of-curry`, thanks—those helper extractions address the complexity finding and keep the policy dispatch clear. 🐇 <!-- <review_comment_addressed> --> --- <!-- This is an auto-generated comment: tweet message by coderabbit.ai --> If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=Caught%20a%20gocyclo%20failure%20at%20complexity%2016%20and%20suggested%20focused%20helpers%20to%20get%20under%20the%20lint%20threshold%20without%20changing%20behavior.%20Ship%20cleaner%20code%20with%20%40coderabbitai%20%F0%9F%9A%80&url=https%3A%2F%2Fgithub.com%2Fsmell-of-curry%2Fgobds%2Fpull%2F81%23discussion_r3583625063)? Thank you for using CodeRabbit! <!-- end of auto-generated comment: tweet message by coderabbit.ai --> <!-- This is an auto-generated reply by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) reviewed 2026-07-16 15:22:53 +00:00
coderabbitai[bot] (Migrated from github.com) commented 2026-07-16 15:22:53 +00:00

@smell-of-curry, understood. Since raw XUID is an intentional, established operational identifier for correlating abuse telemetry, this finding does not apply. I’ll treat this as the accepted telemetry policy for traffic metrics and claim proxy counters.


✏️ Learnings added
Learnt from: smell-of-curry
Repo: smell-of-curry/gobds PR: 81
File: gobds/session/session.go:444-447
Timestamp: 2026-07-16T15:22:46.398Z
Learning: In the GoBDS Go project, raw XUID values are intentionally included in operational abuse telemetry, including session traffic-protection metrics and claim proxy counters, so operators can correlate rate-limit spikes and related events to a player. Do not flag raw XUID emission in these telemetry paths as a privacy issue unless the established operational logging policy changes.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

`@smell-of-curry`, understood. Since raw XUID is an intentional, established operational identifier for correlating abuse telemetry, this finding does not apply. I’ll treat this as the accepted telemetry policy for traffic metrics and claim proxy counters. <!-- <review_comment_withdrawn> --> --- <details> <summary>✏️ Learnings added</summary> ``` Learnt from: smell-of-curry Repo: smell-of-curry/gobds PR: 81 File: gobds/session/session.go:444-447 Timestamp: 2026-07-16T15:22:46.398Z Learning: In the GoBDS Go project, raw XUID values are intentionally included in operational abuse telemetry, including session traffic-protection metrics and claim proxy counters, so operators can correlate rate-limit spikes and related events to a player. Do not flag raw XUID emission in these telemetry paths as a privacy issue unless the established operational logging policy changes. ``` > Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings). </details> <!-- This is an auto-generated reply by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) reviewed 2026-07-16 15:22:56 +00:00
@ -30,0 +128,4 @@
dimensionRange cube.Range,
claims []*claim.PlayerClaim,
denyID uint32,
actor ClaimActor,
coderabbitai[bot] (Migrated from github.com) commented 2026-07-16 15:22:56 +00:00

@smell-of-curry, confirmed. The extraction of resolveClaimSubChunkContext and filterSubChunkEntry, plus hoisting dimensionRangeByID outside the loop, resolves the complexity concern while keeping the handler’s fail-open flow intact.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

`@smell-of-curry`, confirmed. The extraction of `resolveClaimSubChunkContext` and `filterSubChunkEntry`, plus hoisting `dimensionRangeByID` outside the loop, resolves the complexity concern while keeping the handler’s fail-open flow intact. <!-- <review_comment_addressed> --> --- <!-- This is an auto-generated comment: tweet message by coderabbit.ai --> If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=Cut%20%60Handle%60%E2%80%99s%20cyclomatic%20complexity%20by%20extracting%20snapshot%2Fdimension%20resolution%20and%20entry%20filtering%E2%80%94while%20surfacing%20integer-overflow%20risks.%20Cleaner%20CI%2C%20safer%20Go%20code.%20Try%20%40coderabbitai%20%F0%9F%9A%80%F0%9F%9B%A0%EF%B8%8F&url=https%3A%2F%2Fgithub.com%2Fsmell-of-curry%2Fgobds%2Fpull%2F81%23discussion_r3583625045)? Thank you for using CodeRabbit! <!-- end of auto-generated comment: tweet message by coderabbit.ai --> <!-- This is an auto-generated reply by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) reviewed 2026-07-16 15:23:03 +00:00
@ -30,0 +185,4 @@
chunk.EncodeSubChunk(virtualChunk, chunk.NetworkEncoding, int(index)),
blockEntityPayload...,
)
return entry
coderabbitai[bot] (Migrated from github.com) commented 2026-07-16 15:23:03 +00:00

@smell-of-curry, understood — the floor-only deny marker is intentional. My comment assumed full-volume concealment was the goal, so it does not apply. I’m withdrawing it.


✏️ Learnings added
Learnt from: smell-of-curry
Repo: smell-of-curry/gobds PR: 81
File: gobds/session/handler_sub_chunk.go:133-178
Timestamp: 2026-07-16T15:22:58.461Z
Learning: In `gobds/session/handler_sub_chunk.go`, `applyClaimDenyBlocks` intentionally places claim deny-rendering markers only on the dimension-minimum section’s local Y=0 floor layer. It must not rewrite all vertical subchunks, because that would change the intended player-visible rendering and add unnecessary decode/modify cost.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

`@smell-of-curry`, understood — the floor-only deny marker is intentional. My comment assumed full-volume concealment was the goal, so it does not apply. I’m withdrawing it. <!-- <review_comment_withdrawn> --> --- <details> <summary>✏️ Learnings added</summary> ``` Learnt from: smell-of-curry Repo: smell-of-curry/gobds PR: 81 File: gobds/session/handler_sub_chunk.go:133-178 Timestamp: 2026-07-16T15:22:58.461Z Learning: In `gobds/session/handler_sub_chunk.go`, `applyClaimDenyBlocks` intentionally places claim deny-rendering markers only on the dimension-minimum section’s local Y=0 floor layer. It must not rewrite all vertical subchunks, because that would change the intended player-visible rendering and add unnecessary decode/modify cost. ``` > Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings). </details> <!-- This is an auto-generated reply by CodeRabbit -->
Sign in to join this conversation.
No description provided.