Skip to content

fix(ingest): canonicalize DateTime column values to RFC 3339 UTC#402

Open
taitelee wants to merge 16 commits into
mainfrom
canonical-timestamps
Open

fix(ingest): canonicalize DateTime column values to RFC 3339 UTC#402
taitelee wants to merge 16 commits into
mainfrom
canonical-timestamps

Conversation

@taitelee

@taitelee taitelee commented Jul 9, 2026

Copy link
Copy Markdown
Member

Summary

The SSE stream fans out the pre-insert payload verbatim, so a row DateTime reached subscribers in whatever spelling the producer sent (typically zone-less), while /v1/query renders the stored value as RFC 3339 Z — JavaScript parses a zone-less string as local time, landing backfill and live on different clocks.

Ingest now canonicalizes every DateTime/DateTime64 column value to RFC 3339 UTC before the NATS publish, so the one payload every consumer shares (SSE, the ClickHouse insert, the DLQ) matches the query path:

  • Inputs stay liberal: RFC 3339 with any offset, YYYY-MM-DD[ T]HH:MM:SS[.fff], YYYY-MM-DD, and Unix seconds (number or digit-string) all convert. Zone-less strings are interpreted in the column's time zone, else the server's (discovered via SELECT timezone()) — the same rule ClickHouse applies, so the stored instant never changes. Per-column specs (precision + resolved zone) are precomputed at schema refresh, so the per-record path parses no type strings and loads no zones.
  • Canonicalization is fail-open: an unparseable value — or a column whose zone the binary can't resolve (no tzdata embedded; Etc/UTC maps to UTC without it) — publishes verbatim, and ClickHouse's more liberal parser stays the arbiter of insertability, with failures landing in the DLQ as before. Ingest never rejects a record over its timestamp spelling; fail-closed enforcement of the canonical form is the stream row-filter's (fix(stream): apply policy row-filter per subscriber on SSE #381).
  • The worker's insert sets date_time_input_format=best_effort: the default basic parser rejects the canonical form's zone suffix (verified live); best_effort is a superset, so pre-upgrade messages still in NATS parse unchanged.
  • Date/Date32 pass through untouched (day precision, no zone ambiguity on this path).

This is the data-plane foundation for the row-filter timestamp enforcement landing in #381.

Related Issues

Closes #372

@taitelee
taitelee requested review from a team and EricAndrechek July 9, 2026 15:41
@taitelee taitelee moved this from Backlog to In progress in WaveHouse Task Board Jul 9, 2026
@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file go Pull requests that update go code area/api HTTP handlers, routing, middleware area/ingest Ingest pipeline (Bento, batching, DLQ) area/query Structured query AST, SQL builder area/sdk TypeScript SDK (clients/ts/) area/docs Documentation, site/, README area/infra CI, build, deploy, Docker, release labels Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d34fcabf-1fbe-437f-8df2-0fc9384f14c8

📥 Commits

Reviewing files that changed from the base of the PR and between 3f65c5d and e52c3e3.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • docs/src/content/docs/api.md
  • tests/integration/timestamp_canonicalization_test.go
📜 Recent review details
⏰ Context from checks skipped due to timeout. (6)
  • GitHub Check: Docs preview
  • GitHub Check: Unit tests
  • GitHub Check: Integration tests
  • GitHub Check: Coverage
  • GitHub Check: E2E tests
  • GitHub Check: Lint
🧰 Additional context used
📓 Path-based instructions (4)
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Keep documentation synchronized with code changes: update the relevant API, configuration, architecture, deployment, development, or SDK documentation and add every notable change to CHANGELOG.md under Unreleased.

Files:

  • docs/src/content/docs/api.md
  • CHANGELOG.md
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Never force-push or rebase PR branches; merge origin/main instead. Do not hand-write review markers or bypass hooks with --no-verify.
Create agent PRs as drafts with Conventional Commit titles of at most 72 characters, lowercase-first subjects, and no trailing period.
Address every review finding with a substantive reply, a fix or linked tracking issue, and thread resolution before merge.
Prefer one canonical source of truth, comment only the why, and make small safe cleanup improvements within the scope of the change.

Files:

  • docs/src/content/docs/api.md
  • CHANGELOG.md
  • tests/integration/timestamp_canonicalization_test.go
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use Go 1.26, format Go code with gofumpt, return wrapped errors instead of panicking, and pass dependencies explicitly rather than using global state.
Use structured logging with log/slog and JSON handlers.

Files:

  • tests/integration/timestamp_canonicalization_test.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*_test.go: Use table-driven tests with tests := []struct{...} and t.Run(tt.name, ...).
Use shared helpers and mocks from internal/testutil, including JWT, schema, policy, pipes, and JSON response helpers, instead of ad-hoc equivalents.
Every new function should have corresponding test cases; run make lint and make test, and aim for at least 80% coverage on new code.

Files:

  • tests/integration/timestamp_canonicalization_test.go
🧠 Learnings (3)
📚 Learning: 2026-06-10T15:01:09.027Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 312
File: docs/src/content/docs/development.md:0-0
Timestamp: 2026-06-10T15:01:09.027Z
Learning: In this repo’s Markdown review (all .md files), do not flag capitalization/style issues for literal paths starting with ".github/" (or any substring that is a path beginning with ".github/"). Treat ".github" as the correct lowercase dotfile directory name, even when it appears inside prose or code spans; automated checks such as LanguageTool’s "(GITHUB)" rule commonly produce false positives for this literal filesystem path.

Applied to files:

  • docs/src/content/docs/api.md
  • CHANGELOG.md
📚 Learning: 2026-06-26T12:23:22.696Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 346
File: internal/stream/subscriber_test.go:9-28
Timestamp: 2026-06-26T12:23:22.696Z
Learning: In this Go repository, prefer table-driven tests (e.g., `[]struct{...}` with `t.Run(...)`) only for tests that cover multiple scenarios/inputs and can be cleanly enumerated. Do not artificially rewrite a clear single-scenario sequential behavioral-flow test into a table-driven form just to fit the pattern; if there’s only one meaningful scenario, keep the test as a straightforward linear flow (as in `TestSubscriber_SendDeliversThenDropsWhenFull`).

Applied to files:

  • tests/integration/timestamp_canonicalization_test.go
📚 Learning: 2026-07-07T12:38:12.052Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 378
File: internal/auth/auth.go:119-132
Timestamp: 2026-07-07T12:38:12.052Z
Learning: In this repo, do not add or recommend logging/tracing client IP addresses using naive or untrusted sources (e.g., `r.RemoteAddr` or directly trusting/deriving `X-Forwarded-For`) anywhere in the Go codebase. `middleware.RealIP` was removed due to IP-spoofing risks, and proper trusted-proxy-aware client-IP handling is intentionally deferred to issue `#333`. During code review, if proposed changes would record client IPs (including in audit paths such as `internal/auth/auth.go`), reject/redirect until `#333` lands with correct trusted-proxy configuration and safeguards.

Applied to files:

  • tests/integration/timestamp_canonicalization_test.go
🔇 Additional comments (3)
tests/integration/timestamp_canonicalization_test.go (1)

51-88: LGTM!

CHANGELOG.md (1)

53-53: LGTM!

docs/src/content/docs/api.md (1)

220-227: LGTM!


📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Standardized DateTime and DateTime64 values as RFC 3339 UTC timestamps across ingest, streaming, querying, ClickHouse inserts, and dead-letter messages.
    • Supports timezone offsets, fractional seconds, date-only values, and Unix timestamp formats with precision-aware handling.
    • Invalid or unresolved timestamp values continue through unchanged for downstream validation.
  • Documentation

    • Added API, streaming, architecture, and ingest-pipeline documentation for timestamp formatting and compatibility.
  • Tests

    • Added coverage for canonicalization, pass-through behavior, mixed batches, and consistency between streaming and query results.

Walkthrough

WaveHouse adds ingest-time canonicalization for DateTime/DateTime64 values, caches timestamp specifications during schema refresh, configures ClickHouse best-effort parsing, migrates schema-aware test helpers, and documents and tests canonical UTC output across ingest, streaming, querying, and storage.

Changes

Timestamp Canonicalization

Layer / File(s) Summary
Server timezone discovery and schema caching
internal/discovery/..., internal/api/boot_chain_test.go
Schema refresh probes the server timezone, precomputes timestamp specifications, and updates refresh-related test stubs.
Timestamp canonicalization helpers
internal/discovery/timestamp.go, internal/discovery/validation.go, internal/discovery/timestamp_test.go
Adds timestamp detection, parsing, UTC rendering, safe-range checks, and fail-open canonicalization.
Ingest canonicalization before publish
internal/api/ingest.go, internal/api/ingest_test.go, internal/ingest/...
Canonicalizes validated records before publishing and configures ClickHouse inserts for best-effort datetime parsing.
Schema-aware test registry migration
internal/testutil/testutil.go, internal/api/*_test.go
Test registries are populated through the schema refresh path, and API tests use the updated helper.
Documentation and end-to-end validation
docs/src/content/docs/..., AGENTS.md, CHANGELOG.md, tests/e2e/sdk/streaming.test.ts, tests/integration/..., Makefile
Documents the canonical wire form and validates streamed, queried, and ClickHouse-stored timestamp behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant IngestAPI
  participant SchemaRegistry
  participant CanonicalizeTimestamps
  participant Publisher
  participant ClickHouseWorker

  Client->>IngestAPI: POST record with raw DateTime value
  IngestAPI->>SchemaRegistry: load schema with cached timestamp spec
  IngestAPI->>CanonicalizeTimestamps: rewrite timestamp fields
  CanonicalizeTimestamps->>IngestAPI: canonical UTC value or original input
  IngestAPI->>Publisher: publish canonicalized record
  Publisher->>ClickHouseWorker: deliver record for insert
  ClickHouseWorker->>ClickHouseWorker: insert with best-effort datetime parsing
Loading

Suggested reviewers: ericandrechek

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.66% 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
Title check ✅ Passed The title accurately summarizes the main change: ingest-side DateTime canonicalization to RFC 3339 UTC.
Description check ✅ Passed The description is directly aligned with the implemented timestamp canonicalization, docs, and best-effort ingest behavior.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch canonical-timestamps
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch canonical-timestamps

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.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

📚 Docs preview is livehttps://6286a093-wavehouse-docs.wave-rf.workers.dev

  • Commite52c3e3: test: feed the CH oracle production json.Number epochs (>2^53); docs: bullet api.md input forms, six shapes
  • Author@taitelee
  • Committed — 2026-07-16 15:44 (UTC-04:00)
  • Deployed — 2026-07-16 15:52 EDT

@github-code-quality

github-code-quality Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: Go

Go

The overall coverage in the branch remains at 90%, unchanged from the branch.

Show a code coverage summary of the most impacted files.
File c816e34 e52c3e3 +/-
internal/discov...y/validation.go 94% 94% 0%
internal/api/ingest.go 97% 97% 0%
internal/ingest/worker.go 95% 95% 0%
internal/discov...ry/discovery.go 98% 99% +1%
internal/discov...ry/timestamp.go 0% 98% +98%

Updated July 16, 2026 19:53 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions github-actions Bot removed dependencies Pull requests that update a dependency file area/infra CI, build, deploy, Docker, release labels Jul 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 22fa45c5-fbb2-4b42-be1f-3e2fc17b161f

📥 Commits

Reviewing files that changed from the base of the PR and between c816e34 and 0c8272f.

📒 Files selected for processing (14)
  • CHANGELOG.md
  • docs/src/content/docs/api.md
  • go.mod
  • internal/api/boot_chain_test.go
  • internal/api/ingest.go
  • internal/api/ingest_test.go
  • internal/discovery/discovery.go
  • internal/discovery/discovery_test.go
  • internal/discovery/timestamp.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/validation.go
  • internal/ingest/worker.go
  • internal/ingest/worker_test.go
  • tests/e2e/sdk/streaming.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Docs preview
  • GitHub Check: Coverage
  • GitHub Check: E2E tests
  • GitHub Check: Integration tests
🧰 Additional context used
📓 Path-based instructions (2)
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*_test.go: Write tests in table-driven form with t.Run(tt.name, ...) for multiple cases.
Use shared mocks from internal/testutil/ instead of ad-hoc mocks in tests.
Use the repo’s JWT, schema, policy, pipes, and JSON response test helpers (testutil.MakeJWT, testutil.MakeExpiredJWT, NewTestSchemaRegistry, policy.NewMemoryStore, pipes.NewMemoryStore, AssertJSONResponse, AssertJSONContains) where applicable.
Every new function should have corresponding test cases, and new code should aim for 80%+ coverage.

Files:

  • internal/ingest/worker_test.go
  • internal/discovery/discovery_test.go
  • internal/discovery/timestamp_test.go
  • internal/api/ingest_test.go
  • internal/api/boot_chain_test.go
docs/src/content/docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

Documentation prose under the Starlight docs site must stay accurate against code, include runnable examples where relevant, and reflect code↔docs sync for changed behavior.

Files:

  • docs/src/content/docs/api.md
🧠 Learnings (5)
📚 Learning: 2026-06-26T12:23:22.696Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 346
File: internal/stream/subscriber_test.go:9-28
Timestamp: 2026-06-26T12:23:22.696Z
Learning: In this Go repository, prefer table-driven tests (e.g., `[]struct{...}` with `t.Run(...)`) only for tests that cover multiple scenarios/inputs and can be cleanly enumerated. Do not artificially rewrite a clear single-scenario sequential behavioral-flow test into a table-driven form just to fit the pattern; if there’s only one meaningful scenario, keep the test as a straightforward linear flow (as in `TestSubscriber_SendDeliversThenDropsWhenFull`).

Applied to files:

  • internal/ingest/worker_test.go
  • internal/discovery/discovery_test.go
  • internal/discovery/timestamp_test.go
  • internal/api/ingest_test.go
  • internal/api/boot_chain_test.go
📚 Learning: 2026-07-07T12:38:12.052Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 378
File: internal/auth/auth.go:119-132
Timestamp: 2026-07-07T12:38:12.052Z
Learning: In this repo, do not add or recommend logging/tracing client IP addresses using naive or untrusted sources (e.g., `r.RemoteAddr` or directly trusting/deriving `X-Forwarded-For`) anywhere in the Go codebase. `middleware.RealIP` was removed due to IP-spoofing risks, and proper trusted-proxy-aware client-IP handling is intentionally deferred to issue `#333`. During code review, if proposed changes would record client IPs (including in audit paths such as `internal/auth/auth.go`), reject/redirect until `#333` lands with correct trusted-proxy configuration and safeguards.

Applied to files:

  • internal/ingest/worker_test.go
  • internal/ingest/worker.go
  • internal/api/ingest.go
  • internal/discovery/validation.go
  • internal/discovery/discovery_test.go
  • internal/discovery/discovery.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
  • internal/api/ingest_test.go
  • internal/api/boot_chain_test.go
📚 Learning: 2026-06-10T15:01:09.027Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 312
File: docs/src/content/docs/development.md:0-0
Timestamp: 2026-06-10T15:01:09.027Z
Learning: In this repo’s Markdown review (all .md files), do not flag capitalization/style issues for literal paths starting with ".github/" (or any substring that is a path beginning with ".github/"). Treat ".github" as the correct lowercase dotfile directory name, even when it appears inside prose or code spans; automated checks such as LanguageTool’s "(GITHUB)" rule commonly produce false positives for this literal filesystem path.

Applied to files:

  • CHANGELOG.md
  • docs/src/content/docs/api.md
📚 Learning: 2026-05-20T01:02:00.784Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 164
File: internal/api/router_test.go:289-350
Timestamp: 2026-05-20T01:02:00.784Z
Learning: In WaveHouse’s internal API tests (files matching internal/api/**/*_test.go), follow the existing separation-of-concerns convention for testing the RequireRole middleware: inject `ContextKeyRole` directly into the request `context.Context` instead of using `testutil.MakeJWT`/JWT-driven flows. Do not refactor role-gate tests to use JWT tokens—JWT parsing and token handling are covered separately in `middleware_test.go` (the dedicated JWT parsing tests), and mixing those concerns would expand the failure surface and reduce isolation.

Applied to files:

  • internal/api/ingest_test.go
  • internal/api/boot_chain_test.go
📚 Learning: 2026-05-23T01:23:59.268Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 174
File: internal/api/ingest_test.go:111-111
Timestamp: 2026-05-23T01:23:59.268Z
Learning: In WaveHouse Go tests in internal/api/**/*_test.go, use internal/testutil.AssertJSONErrorResponse(t, w) for HTTP error-path JSON assertions. Do not use (or reintroduce) package-local assertJSONErrorResponse helpers. AssertJSONErrorResponse verifies the response Content-Type is application/json, includes the X-Content-Type-Options: nosniff header, and that the JSON body contains an "error" field.

Applied to files:

  • internal/api/ingest_test.go
  • internal/api/boot_chain_test.go
🔇 Additional comments (14)
internal/discovery/discovery.go (1)

71-77: LGTM!

Also applies to: 118-135

internal/discovery/discovery_test.go (1)

112-128: LGTM!

internal/api/boot_chain_test.go (1)

41-57: LGTM!

CHANGELOG.md (1)

49-50: LGTM!

docs/src/content/docs/api.md (1)

220-221: LGTM!

Also applies to: 240-240, 545-546, 776-776

tests/e2e/sdk/streaming.test.ts (1)

80-128: LGTM!

go.mod (1)

3-3: 📐 Maintainability & Code Quality

Keep go 1.26.5 if the toolchain bump is intended

1.26.5 is a valid Go patch release and the current 1.26.x latest, so the version itself looks fine. The only remaining question is whether this minimum-version bump is deliberate for contributors or should be reverted.

internal/discovery/validation.go (1)

51-69: LGTM!

internal/discovery/timestamp_test.go (1)

12-133: LGTM!

internal/api/ingest.go (1)

404-413: LGTM!

internal/api/ingest_test.go (1)

1383-1432: LGTM!

Also applies to: 1450-1482

internal/ingest/worker.go (1)

434-438: LGTM!

internal/ingest/worker_test.go (1)

326-328: LGTM!

internal/discovery/timestamp.go (1)

26-159: Confirm the Go toolchain bump covers these APIs

strings.SplitSeq requires Go 1.24, and for range precision requires Go 1.22+. Make sure go.mod targets at least Go 1.24 before merging.

Comment thread internal/api/ingest_test.go Outdated
Comment thread internal/discovery/discovery.go Outdated
@github-project-automation github-project-automation Bot moved this from In progress to In review in WaveHouse Task Board Jul 9, 2026
@github-actions github-actions Bot added the area/infra CI, build, deploy, Docker, release label Jul 9, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 9, 2026
…nical wire-form invariant

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: fc33ad16-18ec-4fcd-9f2a-a02e315de790

📥 Commits

Reviewing files that changed from the base of the PR and between 0c8272f and 7607472.

📒 Files selected for processing (10)
  • AGENTS.md
  • CHANGELOG.md
  • cmd/wavehouse/main.go
  • docs/src/content/docs/api.md
  • docs/src/content/docs/architecture.md
  • internal/api/ingest.go
  • internal/api/ingest_test.go
  • internal/discovery/discovery.go
  • internal/discovery/timestamp.go
  • internal/discovery/timestamp_test.go
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
  • GitHub Check: Docs preview
  • GitHub Check: Coverage
  • GitHub Check: Integration tests
  • GitHub Check: E2E tests
  • GitHub Check: Unit tests
  • GitHub Check: Lint
🧰 Additional context used
📓 Path-based instructions (4)
docs/src/content/docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

Keep documentation accurate, runnable, and synchronized with code changes; update architecture, API, configuration, deployment, or development docs as relevant.

Files:

  • docs/src/content/docs/architecture.md
  • docs/src/content/docs/api.md
CHANGELOG.md

📄 CodeRabbit inference engine (AGENTS.md)

Record notable changes under [Unreleased] when a change affects user-visible behavior or project conventions.

Files:

  • CHANGELOG.md
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

Use shared mocks from internal/testutil/ instead of ad-hoc mocks, and prefer the provided JWT, schema, policy, pipes, and JSON response helpers in tests.

Files:

  • internal/api/ingest_test.go
  • internal/discovery/timestamp_test.go
internal/discovery/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Preserve schema discovery and timestamp canonicalization behavior: ingest timestamps must be rewritten to canonical RFC 3339 UTC before publish.

Files:

  • internal/discovery/discovery.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Validate locally before every push by running `make ci` the documented way; do not rely on CI as the first feedback loop.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: For PR-branch pushes, run `/prepush` and ensure every required pre-push reviewer from `scripts/pre-push-reviewers.sh` reaches `ship_it` or is deliberately skipped on the record.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Every code change must update its corresponding documentation and `CHANGELOG.md` in the same PR.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Address and resolve every review finding; reply substantively, fix it or track it in an issue, and never silently drop a thread.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Agents must create draft PRs only, and PR titles must pass the Conventional Commits lint rules (≤72 chars, lowercase-first subject, no trailing period).
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Never force-push or rebase a PR branch; merge upstream main instead with `git merge origin/main`.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Never hand-write review markers or use `--no-verify`; use the documented gates and skip tooling instead.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Comment the why, not the what; only add comments when the reason is not obvious from the code, and keep them short.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Prefer DRY, with one source of truth for shared logic and canonical scripts for repeated repo rules.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Leave touched code neater than you found it by fixing small safe issues in the same scope, but avoid risky cleanup.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-09T17:18:37.453Z
Learning: Use table-driven tests with `t.Run(tt.name, ...)` for multiple scenarios.
📚 Learning: 2026-07-07T12:38:12.052Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 378
File: internal/auth/auth.go:119-132
Timestamp: 2026-07-07T12:38:12.052Z
Learning: In this repo, do not add or recommend logging/tracing client IP addresses using naive or untrusted sources (e.g., `r.RemoteAddr` or directly trusting/deriving `X-Forwarded-For`) anywhere in the Go codebase. `middleware.RealIP` was removed due to IP-spoofing risks, and proper trusted-proxy-aware client-IP handling is intentionally deferred to issue `#333`. During code review, if proposed changes would record client IPs (including in audit paths such as `internal/auth/auth.go`), reject/redirect until `#333` lands with correct trusted-proxy configuration and safeguards.

Applied to files:

  • cmd/wavehouse/main.go
  • internal/api/ingest.go
  • internal/api/ingest_test.go
  • internal/discovery/discovery.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
📚 Learning: 2026-06-10T15:01:09.027Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 312
File: docs/src/content/docs/development.md:0-0
Timestamp: 2026-06-10T15:01:09.027Z
Learning: In this repo’s Markdown review (all .md files), do not flag capitalization/style issues for literal paths starting with ".github/" (or any substring that is a path beginning with ".github/"). Treat ".github" as the correct lowercase dotfile directory name, even when it appears inside prose or code spans; automated checks such as LanguageTool’s "(GITHUB)" rule commonly produce false positives for this literal filesystem path.

Applied to files:

  • docs/src/content/docs/architecture.md
  • CHANGELOG.md
  • AGENTS.md
  • docs/src/content/docs/api.md
📚 Learning: 2026-05-20T01:02:00.784Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 164
File: internal/api/router_test.go:289-350
Timestamp: 2026-05-20T01:02:00.784Z
Learning: In WaveHouse’s internal API tests (files matching internal/api/**/*_test.go), follow the existing separation-of-concerns convention for testing the RequireRole middleware: inject `ContextKeyRole` directly into the request `context.Context` instead of using `testutil.MakeJWT`/JWT-driven flows. Do not refactor role-gate tests to use JWT tokens—JWT parsing and token handling are covered separately in `middleware_test.go` (the dedicated JWT parsing tests), and mixing those concerns would expand the failure surface and reduce isolation.

Applied to files:

  • internal/api/ingest_test.go
📚 Learning: 2026-05-23T01:23:59.268Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 174
File: internal/api/ingest_test.go:111-111
Timestamp: 2026-05-23T01:23:59.268Z
Learning: In WaveHouse Go tests in internal/api/**/*_test.go, use internal/testutil.AssertJSONErrorResponse(t, w) for HTTP error-path JSON assertions. Do not use (or reintroduce) package-local assertJSONErrorResponse helpers. AssertJSONErrorResponse verifies the response Content-Type is application/json, includes the X-Content-Type-Options: nosniff header, and that the JSON body contains an "error" field.

Applied to files:

  • internal/api/ingest_test.go
📚 Learning: 2026-06-26T12:23:22.696Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 346
File: internal/stream/subscriber_test.go:9-28
Timestamp: 2026-06-26T12:23:22.696Z
Learning: In this Go repository, prefer table-driven tests (e.g., `[]struct{...}` with `t.Run(...)`) only for tests that cover multiple scenarios/inputs and can be cleanly enumerated. Do not artificially rewrite a clear single-scenario sequential behavioral-flow test into a table-driven form just to fit the pattern; if there’s only one meaningful scenario, keep the test as a straightforward linear flow (as in `TestSubscriber_SendDeliversThenDropsWhenFull`).

Applied to files:

  • internal/api/ingest_test.go
  • internal/discovery/timestamp_test.go
📚 Learning: 2026-07-09T16:20:50.620Z
Learnt from: taitelee
Repo: Wave-RF/WaveHouse PR: 402
File: internal/api/ingest_test.go:1434-1448
Timestamp: 2026-07-09T16:20:50.620Z
Learning: In WaveHouse’s Go schema/timestamp handling (internal/discovery), resolve any timestamp column zone/precision requirements exactly once during SchemaRegistry.Refresh() and cache the resolved specs on the column. Do not resolve zones per-record on the hot path. Ensure timezone resolution uses embedded tzdata (e.g., via cmd/wavehouse’s time.LoadLocation + embedded tzdata) so minimal containers don’t silently fall back to UTC for non-UTC ClickHouse servers, which would corrupt stored instants. Treat timezone-resolution failures during refresh as non-fatal: keep boot alive, RetryRefresh should continue retrying, and readiness/health (/livez) should surface a degraded state. If a column’s timezone cannot be resolved after refresh, emit a warning and reject only that column’s timestamp values per-record rather than failing the entire refresh.

Applied to files:

  • internal/discovery/discovery.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
🔇 Additional comments (11)
internal/discovery/discovery.go (1)

22-28: LGTM!

Also applies to: 71-96, 130-137, 236-247

internal/api/ingest_test.go (1)

1411-1432: LGTM!

Also applies to: 1434-1448, 1450-1482

docs/src/content/docs/api.md (1)

220-221: LGTM!

Also applies to: 240-240, 545-546, 776-776

CHANGELOG.md (1)

53-54: LGTM!

cmd/wavehouse/main.go (1)

17-23: LGTM!

internal/discovery/timestamp.go (2)

44-71: LGTM!

Also applies to: 73-80, 82-105, 107-147, 196-207


119-119: 🎯 Functional Correctness

No Go version compatibility issue here. go 1.26.5 already supports strings.SplitSeq and range-over-function syntax.

			> Likely an incorrect or invalid review comment.
internal/discovery/timestamp_test.go (1)

47-91: LGTM!

Also applies to: 93-101, 105-114, 116-140, 142-171, 173-182

internal/api/ingest.go (1)

404-414: LGTM!

AGENTS.md (1)

37-37: LGTM!

docs/src/content/docs/architecture.md (1)

116-117: LGTM!

Also applies to: 171-173

Comment thread AGENTS.md Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 9, 2026
@taitelee taitelee moved this from In review to Ready in WaveHouse Task Board Jul 10, 2026

@EricAndrechek EricAndrechek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'm sending this back without detailed comments on much else because timezones and time parsing scares me, and I see exactly 0 tests that actually run e2e with a full clickhouse instance and various variations of datetime w/ and w/out timezone, varying degrees of precision, etc columns in their schema that we test against. For instance, what happens if you send "20260711", or "202607111500"? Does ClickHouse, with best_effort turned on now, interpret these as YYYYMMDD and YYYYMMDDHHMMSS, or as unix seconds?

Also, worth reading falsehoods programmers believe about time and more falsehoods programmers believe about time – basically, it scares me a lot to do this much, and I am POSITIVE that if we started fuzzing this end-to-end with random inputs, we wouldn't have to wait very long before the time we parsed it as differed from the time clickhouse parsed it as...

So in essence, I really think we need to figure out how to be FAR more strict about what the time coming in is when parsing it or its timezone, and only use that if we are ABSOLUTELY sure we know the format they used, etc. Good luck, times are hard. :)

Comment thread internal/discovery/discovery.go Outdated
Comment thread internal/discovery/timestamp.go
Comment thread internal/discovery/discovery.go
@github-project-automation github-project-automation Bot moved this from Ready to In review in WaveHouse Task Board Jul 11, 2026
@github-actions github-actions Bot added the area/infra CI, build, deploy, Docker, release label Jul 13, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ee110756-6915-4e62-b4ff-69b5bdd25e2c

📥 Commits

Reviewing files that changed from the base of the PR and between 844e712 and de96ab3.

📒 Files selected for processing (20)
  • AGENTS.md
  • CHANGELOG.md
  • Makefile
  • docs/src/content/docs/api.md
  • docs/src/content/docs/architecture.md
  • docs/src/content/docs/ingest-pipeline.md
  • internal/api/errors_test.go
  • internal/api/ingest.go
  • internal/api/ingest_test.go
  • internal/api/router_test.go
  • internal/api/schema_test.go
  • internal/api/structured_query_test.go
  • internal/discovery/discovery.go
  • internal/discovery/discovery_test.go
  • internal/discovery/timestamp.go
  • internal/discovery/timestamp_test.go
  • internal/ingest/worker.go
  • internal/ingest/worker_test.go
  • internal/testutil/testutil.go
  • tests/integration/timestamp_canonicalization_test.go
💤 Files with no reviewable changes (1)
  • internal/ingest/worker.go
📜 Review details
⏰ Context from checks skipped due to timeout. (7)
  • GitHub Check: Docs preview
  • GitHub Check: E2E tests
  • GitHub Check: Unit tests
  • GitHub Check: Coverage
  • GitHub Check: Integration tests
  • GitHub Check: Lint
  • GitHub Check: Analyze (go)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use Go 1.26 with strict gofumpt formatting.
Use structured logging with log/slog and JSON handlers.
Use Chi v5 for HTTP routing.
Return errors instead of panicking, and wrap errors with fmt.Errorf("context: %w", err).
Avoid global state; pass dependencies explicitly through constructor injection.
Comment the why, not the what; keep comments to one or two lines and omit comments that merely restate code.

Files:

  • internal/api/schema_test.go
  • internal/ingest/worker_test.go
  • internal/api/ingest.go
  • tests/integration/timestamp_canonicalization_test.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/testutil/testutil.go
  • internal/discovery/discovery_test.go
  • internal/api/structured_query_test.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
  • internal/api/ingest_test.go
  • internal/discovery/discovery.go
internal/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Use lowercase, single-word or abbreviated package names; keep implementation packages under internal/ for module privacy.

Files:

  • internal/api/schema_test.go
  • internal/ingest/worker_test.go
  • internal/api/ingest.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/testutil/testutil.go
  • internal/discovery/discovery_test.go
  • internal/api/structured_query_test.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
  • internal/api/ingest_test.go
  • internal/discovery/discovery.go
**/*.{go,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer one source of truth and reuse existing helpers, types, and constants instead of duplicating logic.

Files:

  • internal/api/schema_test.go
  • internal/ingest/worker_test.go
  • internal/api/ingest.go
  • tests/integration/timestamp_canonicalization_test.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/testutil/testutil.go
  • internal/discovery/discovery_test.go
  • internal/api/structured_query_test.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
  • internal/api/ingest_test.go
  • internal/discovery/discovery.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*_test.go: Use table-driven tests with tests := []struct{...} and t.Run(tt.name, ...) for multiple scenarios.
Every new function should have corresponding test cases; aim for at least 80% coverage on new code.

Files:

  • internal/api/schema_test.go
  • internal/ingest/worker_test.go
  • tests/integration/timestamp_canonicalization_test.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/discovery/discovery_test.go
  • internal/api/structured_query_test.go
  • internal/discovery/timestamp_test.go
  • internal/api/ingest_test.go
internal/**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

internal/**/*_test.go: Use shared mocks from internal/testutil/ instead of creating ad-hoc mocks.
Use testutil.MakeJWT, MakeExpiredJWT, NewTestSchemaRegistry, AssertJSONResponse, and AssertJSONContains for the corresponding tests.

Files:

  • internal/api/schema_test.go
  • internal/ingest/worker_test.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/discovery/discovery_test.go
  • internal/api/structured_query_test.go
  • internal/discovery/timestamp_test.go
  • internal/api/ingest_test.go
docs/src/content/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Keep documentation synchronized with code changes, including API, configuration, architecture, deployment, ingest/event-format, development-process, and notable-change documentation as applicable.

Files:

  • docs/src/content/docs/ingest-pipeline.md
  • docs/src/content/docs/api.md
  • docs/src/content/docs/architecture.md
CHANGELOG.md

📄 CodeRabbit inference engine (AGENTS.md)

Record every notable code change under [Unreleased].

Files:

  • CHANGELOG.md
internal/discovery/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Canonicalize parseable DateTime and DateTime64 ingest values to RFC 3339 UTC before publishing, but fail open and publish unparseable or unresolvable values verbatim.

Files:

  • internal/discovery/discovery_test.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
  • internal/discovery/discovery.go
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-13T17:33:30.271Z
Learning: Run `make ci` locally before every push; for agents, run it in the background with output redirected to `tmp/ci.log` and no pipes.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-13T17:33:30.271Z
Learning: Never force-push or rebase a PR branch; merge `origin/main` instead.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-13T17:33:30.271Z
Learning: Create agent PRs as drafts with a Conventional Commits title of at most 72 characters, validated by `scripts/lint-pr-title.sh`.
Learnt from: CR
Repo: Wave-RF/WaveHouse

Timestamp: 2026-07-13T17:33:30.271Z
Learning: Never hand-write review or CI markers and never bypass gates with `--no-verify`; run or deliberately skip required reviewers through the provided tooling.
📚 Learning: 2026-05-20T01:02:00.784Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 164
File: internal/api/router_test.go:289-350
Timestamp: 2026-05-20T01:02:00.784Z
Learning: In WaveHouse’s internal API tests (files matching internal/api/**/*_test.go), follow the existing separation-of-concerns convention for testing the RequireRole middleware: inject `ContextKeyRole` directly into the request `context.Context` instead of using `testutil.MakeJWT`/JWT-driven flows. Do not refactor role-gate tests to use JWT tokens—JWT parsing and token handling are covered separately in `middleware_test.go` (the dedicated JWT parsing tests), and mixing those concerns would expand the failure surface and reduce isolation.

Applied to files:

  • internal/api/schema_test.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/api/structured_query_test.go
  • internal/api/ingest_test.go
📚 Learning: 2026-05-23T01:23:59.268Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 174
File: internal/api/ingest_test.go:111-111
Timestamp: 2026-05-23T01:23:59.268Z
Learning: In WaveHouse Go tests in internal/api/**/*_test.go, use internal/testutil.AssertJSONErrorResponse(t, w) for HTTP error-path JSON assertions. Do not use (or reintroduce) package-local assertJSONErrorResponse helpers. AssertJSONErrorResponse verifies the response Content-Type is application/json, includes the X-Content-Type-Options: nosniff header, and that the JSON body contains an "error" field.

Applied to files:

  • internal/api/schema_test.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/api/structured_query_test.go
  • internal/api/ingest_test.go
📚 Learning: 2026-06-26T12:23:22.696Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 346
File: internal/stream/subscriber_test.go:9-28
Timestamp: 2026-06-26T12:23:22.696Z
Learning: In this Go repository, prefer table-driven tests (e.g., `[]struct{...}` with `t.Run(...)`) only for tests that cover multiple scenarios/inputs and can be cleanly enumerated. Do not artificially rewrite a clear single-scenario sequential behavioral-flow test into a table-driven form just to fit the pattern; if there’s only one meaningful scenario, keep the test as a straightforward linear flow (as in `TestSubscriber_SendDeliversThenDropsWhenFull`).

Applied to files:

  • internal/api/schema_test.go
  • internal/ingest/worker_test.go
  • tests/integration/timestamp_canonicalization_test.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/discovery/discovery_test.go
  • internal/api/structured_query_test.go
  • internal/discovery/timestamp_test.go
  • internal/api/ingest_test.go
📚 Learning: 2026-07-07T12:38:12.052Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 378
File: internal/auth/auth.go:119-132
Timestamp: 2026-07-07T12:38:12.052Z
Learning: In this repo, do not add or recommend logging/tracing client IP addresses using naive or untrusted sources (e.g., `r.RemoteAddr` or directly trusting/deriving `X-Forwarded-For`) anywhere in the Go codebase. `middleware.RealIP` was removed due to IP-spoofing risks, and proper trusted-proxy-aware client-IP handling is intentionally deferred to issue `#333`. During code review, if proposed changes would record client IPs (including in audit paths such as `internal/auth/auth.go`), reject/redirect until `#333` lands with correct trusted-proxy configuration and safeguards.

Applied to files:

  • internal/api/schema_test.go
  • internal/ingest/worker_test.go
  • internal/api/ingest.go
  • tests/integration/timestamp_canonicalization_test.go
  • internal/api/errors_test.go
  • internal/api/router_test.go
  • internal/testutil/testutil.go
  • internal/discovery/discovery_test.go
  • internal/api/structured_query_test.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
  • internal/api/ingest_test.go
  • internal/discovery/discovery.go
📚 Learning: 2026-06-10T15:01:09.027Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 312
File: docs/src/content/docs/development.md:0-0
Timestamp: 2026-06-10T15:01:09.027Z
Learning: In this repo’s Markdown review (all .md files), do not flag capitalization/style issues for literal paths starting with ".github/" (or any substring that is a path beginning with ".github/"). Treat ".github" as the correct lowercase dotfile directory name, even when it appears inside prose or code spans; automated checks such as LanguageTool’s "(GITHUB)" rule commonly produce false positives for this literal filesystem path.

Applied to files:

  • docs/src/content/docs/ingest-pipeline.md
  • CHANGELOG.md
  • docs/src/content/docs/api.md
  • docs/src/content/docs/architecture.md
  • AGENTS.md
📚 Learning: 2026-07-09T16:20:50.620Z
Learnt from: taitelee
Repo: Wave-RF/WaveHouse PR: 402
File: internal/api/ingest_test.go:1434-1448
Timestamp: 2026-07-09T16:20:50.620Z
Learning: In WaveHouse’s Go schema/timestamp handling (internal/discovery), resolve any timestamp column zone/precision requirements exactly once during SchemaRegistry.Refresh() and cache the resolved specs on the column. Do not resolve zones per-record on the hot path. Ensure timezone resolution uses embedded tzdata (e.g., via cmd/wavehouse’s time.LoadLocation + embedded tzdata) so minimal containers don’t silently fall back to UTC for non-UTC ClickHouse servers, which would corrupt stored instants. Treat timezone-resolution failures during refresh as non-fatal: keep boot alive, RetryRefresh should continue retrying, and readiness/health (/livez) should surface a degraded state. If a column’s timezone cannot be resolved after refresh, emit a warning and reject only that column’s timestamp values per-record rather than failing the entire refresh.

Applied to files:

  • internal/discovery/discovery_test.go
  • internal/discovery/timestamp_test.go
  • internal/discovery/timestamp.go
  • internal/discovery/discovery.go
🪛 ast-grep (0.44.1)
tests/integration/timestamp_canonicalization_test.go

[error] 156-157: Detected a SQL query built with 'fmt.Sprintf' and passed directly to a 'database/sql' query method (Query, QueryRow, QueryContext, or QueryRowContext). Formatting user-controlled values into a query string enables SQL injection. Use parameterized queries with placeholders (e.g. 'db.Query("SELECT * FROM users WHERE id = ", id)') and pass arguments separately instead of interpolating them with 'fmt.Sprintf'.
Context: env(t).chConn.QueryRow(context.Background(),
fmt.Sprintf("SELECT v FROM %s WHERE id = ?", table), id)
Note: [CWE-89] Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection').

(sql-injection-query-sprintf-go)


[warning] 92-92: 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: uint32(i)
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)

🔇 Additional comments (26)
internal/api/ingest_test.go (1)

23-36: LGTM!

Also applies to: 1385-1489

internal/ingest/worker_test.go (1)

314-349: LGTM!

internal/testutil/testutil.go (2)

4-13: LGTM!

Also applies to: 27-39, 41-66, 70-110


68-69: 🎯 Functional Correctness

Possible duplicate utcRow declaration. The snippet shows type utcRow struct{ driver.Row } twice in a row; if that's in the source, it will fail to compile.

internal/api/errors_test.go (1)

164-164: LGTM!

Also applies to: 192-213

internal/api/router_test.go (1)

279-334: LGTM!

Also applies to: 409-468, 470-505, 521-544, 546-570, 644-687

internal/api/schema_test.go (1)

16-33: LGTM!

Also applies to: 35-56, 58-71

internal/api/structured_query_test.go (1)

32-44: LGTM!

Also applies to: 76-99, 101-111, 113-123, 130-153, 155-181, 183-211, 213-247, 249-262, 282-296

docs/src/content/docs/architecture.md (3)

184-187: 🎯 Functional Correctness

Verify the "server default since ClickHouse 26.5" claim.

See consolidated comment (anchored here) — this exact claim is repeated in ingest-pipeline.md and CHANGELOG.md and could not be corroborated against current ClickHouse documentation.


116-117: LGTM!

Also applies to: 171-173


1-1: 📐 Maintainability & Code Quality | ⚡ Quick win

Unverified claim: best_effort became ClickHouse's default date_time_input_format "since 26.5". All three docs assert this specific version made best_effort the server default. A web search against ClickHouse's own current docs and blog turned up no confirmation of this change — multiple sources (including a ClickHouse blog post and third-party guides) still describe basic as the default with no mention of a 26.5 default flip, and the 26.5 release blog's own feature list doesn't mention this setting. Since the worker already pins date_time_input_format=best_effort explicitly on every insert (confirmed in tests/integration/timestamp_canonicalization_test.go's insertBestEffort), this claim has no functional impact, but it's a specific, falsifiable version claim repeated three times and worth double-checking before it ships as documentation fact.

  • docs/src/content/docs/architecture.md#L184-187: verify or soften the "server default since ClickHouse 26.5" claim (or drop the specific version if it can't be confirmed against ClickHouse's release notes).
  • docs/src/content/docs/ingest-pipeline.md#L30-34: same claim, same fix.
  • CHANGELOG.md#L53-54: same claim ("verified live") — if this was empirically verified against a specific ClickHouse build, consider citing that build/commit rather than a general version-default assertion that public docs don't corroborate.
docs/src/content/docs/ingest-pipeline.md (1)

30-34: 🎯 Functional Correctness

Verify the "server default since ClickHouse 26.5" claim.

See consolidated comment (anchored on architecture.md) — this claim is repeated here and in CHANGELOG.md.

CHANGELOG.md (2)

53-54: 🗄️ Data Integrity & Integration

Two claims here are shared with other files — see consolidated comments.

(1) The "server default since ClickHouse 26.5" claim, anchored on architecture.md. (2) The "unresolvable zone... never a failed refresh" blanket wording, anchored on AGENTS.md.


372-372: LGTM!

docs/src/content/docs/api.md (1)

220-230: LGTM!

Also applies to: 553-554, 784-784

AGENTS.md (3)

68-68: 📐 Maintainability & Code Quality

Confirm the fail-open wording still distinguishes the two zone-resolution tiers.

Per the earlier thread on this line, an unresolvable server-default zone deliberately fails Refresh() (discovery.go:87-95, non-fatal only because boot wraps it in RetryRefresh), while an unresolvable column-declared zone only warns and defers to ingest. The current sentence — "an unparseable value or unresolvable zone … never a failed refresh" — still reads as one blanket claim rather than the two-tier split the maintainer said would be spelled out here. Worth a final check that this is intentionally scoped to ingest-time processing only, not a reintroduction of the earlier ambiguity. See consolidated comment (anchored here) for the matching CHANGELOG.md sentence.

Based on learnings from the prior review thread on this file/paragraph.


124-124: LGTM!

Also applies to: 382-382


1-1: 📐 Maintainability & Code Quality

Re-confirm the fail-open zone wording still reflects the two-tier split from the prior review thread. A previous review on this repo established that an unresolvable server-default zone deliberately fails SchemaRegistry.Refresh() (non-fatal only because boot wraps it in RetryRefresh), while an unresolvable column-declared zone only warns and defers to per-record ingest rejection — and the maintainer committed to rewording both AGENTS.md and the matching CHANGELOG.md sentence to state both tiers explicitly. Both sentences here still read as one blanket "never a failed refresh" claim rather than the two-tier split; worth a final check that this is intentionally scoped to ingest-time-only behavior (where no refresh occurs) and not a reintroduction of the earlier conflation.

  • AGENTS.md#L68-68: confirm "an unparseable value or unresolvable zone … never a failed refresh" doesn't need to carve out the server-default-zone-fails-refresh case.
  • CHANGELOG.md#L53-54: confirm the matching "an unresolvable zone … never a failed refresh" sentence has the same scoping.

Based on learnings from the prior review thread on this exact AGENTS.md paragraph and its CHANGELOG.md counterpart.

Makefile (1)

675-683: LGTM!

tests/integration/timestamp_canonicalization_test.go (2)

1-153: LGTM!


154-160: 🔒 Security & Privacy

Confirm table-name provenance here
If createTable can ever incorporate caller-controlled input, this fmt.Sprintf("SELECT v FROM %s WHERE id = ?", table) needs identifier binding like insertBestEffort uses for the INSERT path.

internal/discovery/discovery_test.go (2)

99-183: 📐 Maintainability & Code Quality

Ad-hoc fakeConn/fakeRows mocks likely duplicate testutil's fake conn.

internal/testutil/testutil.go already appears to implement an equivalent fake driver.Conn (Query, Scan, Next, Close, Err) backing NewTestSchemaRegistry. A prior reviewer already asked to move this kind of mock into test utils. As per path instructions for internal/**/*_test.go: "Use shared mocks from internal/testutil/ instead of creating ad-hoc mocks."

This may be structurally blocked by an import cycle (discovery_test.go is package discovery, and if testutil imports discovery for NewTestSchemaRegistry's signature, discovery can't import testutil back). Please confirm whether that cycle is real; if so, this duplication may be unavoidable without restructuring testutil (e.g., splitting off a cycle-free sub-package), but that's worth an explicit decision rather than silently re-duplicating the mock.

#!/bin/bash
# Confirm testutil's fake-conn surface and whether it imports discovery (⇒ cycle risk for discovery_test.go).
fd testutil.go
rg -n 'package|^import|"Wave-RF/WaveHouse/internal/discovery"|func.*Query|func.*Scan|func.*Next|func.*Close|func.*Err' internal/testutil/testutil.go -A1
rg -n '^package' internal/discovery/discovery_test.go

Sources: Coding guidelines, Path instructions


391-411: 🩺 Stability & Availability

Check StartAutoRefresh order — if it triggers an initial Refresh before observing ctx.Done(), this test will hit the nil conn path and panic.

internal/discovery/discovery.go (1)

16-27: LGTM!

Also applies to: 71-135

internal/discovery/timestamp.go (1)

36-52: LGTM!

Also applies to: 89-136, 138-164, 166-223, 225-283

internal/discovery/timestamp_test.go (1)

48-103: LGTM!

Also applies to: 130-194, 198-228, 230-241

Comment thread internal/api/ingest.go Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 13, 2026
@taitelee taitelee moved this from In review to Ready in WaveHouse Task Board Jul 15, 2026
@taitelee

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 15, 2026
Comment thread tests/integration/timestamp_canonicalization_test.go Outdated
Comment thread docs/src/content/docs/api.md Outdated
Comment thread CHANGELOG.md Outdated
@taitelee
taitelee requested a review from EricAndrechek July 16, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api HTTP handlers, routing, middleware area/docs Documentation, site/, README area/infra CI, build, deploy, Docker, release area/ingest Ingest pipeline (Bento, batching, DLQ) area/query Structured query AST, SQL builder area/sdk TypeScript SDK (clients/ts/) documentation Improvements or additions to documentation go Pull requests that update go code

Projects

Status: Ready

Development

Successfully merging this pull request may close these issues.

bug(streaming): SSE /v1/stream emits row DateTime columns zone-less while /v1/query uses RFC3339 Z

2 participants