From 3283f9dfdf5ed9e5a5ac46057ada2d24ae9c88bc Mon Sep 17 00:00:00 2001 From: Miya Date: Thu, 8 Oct 2026 03:53:38 +0200 Subject: [PATCH] fix(checkpoint): cap complete upstream cursor at 512 characters --- cmd/relayfile-cli/checkpoint_lifecycle.go | 2 +- cmd/relayfile-cli/checkpoint_lifecycle_test.go | 4 ++-- internal/mountsync/syncer.go | 2 +- internal/mountsync/syncer_test.go | 4 ++-- internal/relayfile/checkpoint_seal.go | 2 +- internal/relayfile/checkpoint_seal_test.go | 4 ++-- openapi/relayfile-v1.openapi.yaml | 6 +++--- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/relayfile-cli/checkpoint_lifecycle.go b/cmd/relayfile-cli/checkpoint_lifecycle.go index 113c5c80..7de4efa1 100644 --- a/cmd/relayfile-cli/checkpoint_lifecycle.go +++ b/cmd/relayfile-cli/checkpoint_lifecycle.go @@ -39,7 +39,7 @@ var ( checkpointLifecycleIDPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$`) checkpointDigestPattern = regexp.MustCompile(`^sha256:[0-9a-f]{64}$`) checkpointRevisionPattern = regexp.MustCompile(`^(?:0|rev_[0-9]+)$`) - checkpointCursorPattern = regexp.MustCompile(`^(?:0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,501})$`) + checkpointCursorPattern = regexp.MustCompile(`^(?:0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,500})$`) ) type checkpointCLIError struct { diff --git a/cmd/relayfile-cli/checkpoint_lifecycle_test.go b/cmd/relayfile-cli/checkpoint_lifecycle_test.go index 540da9ac..3ea124eb 100644 --- a/cmd/relayfile-cli/checkpoint_lifecycle_test.go +++ b/cmd/relayfile-cli/checkpoint_lifecycle_test.go @@ -25,8 +25,8 @@ type fakeCheckpointLease struct{ released bool } func (l *fakeCheckpointLease) Release() error { l.released = true; return nil } func TestCheckpointCursorPattern(t *testing.T) { - valid := []string{"0", "evt_42", "upstream:v1:notion:page_123", "upstream:v1:notion:page_123:2", "upstream:v1:" + strings.Repeat("a", 501)} - invalid := []string{"", " ", "evt_", "upstream:v1:", "upstream:v1:notion page_123", " upstream:v1:notion:page_123 ", "upstream:v1:notion\npage_123", "upstream:v1:slack:bad\\id", "upstream:v1:slack:bad\x7fid", "upstream:v1:" + strings.Repeat("a", 502)} + valid := []string{"0", "evt_42", "upstream:v1:notion:page_123", "upstream:v1:notion:page_123:2", "upstream:v1:" + strings.Repeat("a", 500)} + invalid := []string{"", " ", "evt_", "upstream:v1:", "upstream:v1:notion page_123", " upstream:v1:notion:page_123 ", "upstream:v1:notion\npage_123", "upstream:v1:slack:bad\\id", "upstream:v1:slack:bad\x7fid", "upstream:v1:" + strings.Repeat("a", 501)} for _, cursor := range valid { if !checkpointCursorPattern.MatchString(cursor) { t.Errorf("valid cursor rejected: %q", cursor) diff --git a/internal/mountsync/syncer.go b/internal/mountsync/syncer.go index 698a2a72..b8666edd 100644 --- a/internal/mountsync/syncer.go +++ b/internal/mountsync/syncer.go @@ -51,7 +51,7 @@ var ( ErrCheckpointNonConverged = errors.New("local and durable Relayfile state did not converge") checkpointSessionPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$`) checkpointRevisionPattern = regexp.MustCompile(`^(?:0|rev_[0-9]+)$`) - checkpointEventCursorPattern = regexp.MustCompile(`^(?:0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,501})$`) + checkpointEventCursorPattern = regexp.MustCompile(`^(?:0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,500})$`) mountCorrelationIDPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$`) ) diff --git a/internal/mountsync/syncer_test.go b/internal/mountsync/syncer_test.go index d6895c76..e07ede4b 100644 --- a/internal/mountsync/syncer_test.go +++ b/internal/mountsync/syncer_test.go @@ -10948,7 +10948,7 @@ func TestCheckpointEventCursorPattern(t *testing.T) { "evt_42", "upstream:v1:linear:issue_123", "upstream:v1:linear:issue_123:2", - "upstream:v1:" + strings.Repeat("a", 501), + "upstream:v1:" + strings.Repeat("a", 500), } invalid := []string{ "", @@ -10960,7 +10960,7 @@ func TestCheckpointEventCursorPattern(t *testing.T) { " upstream:v1:linear:issue_123 ", "upstream:v1:linear/issue_123", "upstream:v1:linear\nissue_123", - "upstream:v1:slack:bad\\id", "upstream:v1:slack:bad\x7fid", "upstream:v1:" + strings.Repeat("a", 502), + "upstream:v1:slack:bad\\id", "upstream:v1:slack:bad\x7fid", "upstream:v1:" + strings.Repeat("a", 501), } for _, cursor := range valid { if !checkpointEventCursorPattern.MatchString(cursor) { diff --git a/internal/relayfile/checkpoint_seal.go b/internal/relayfile/checkpoint_seal.go index 91a0863c..e2c81db0 100644 --- a/internal/relayfile/checkpoint_seal.go +++ b/internal/relayfile/checkpoint_seal.go @@ -37,7 +37,7 @@ var ( ErrCheckpointAdminConflict = errors.New("checkpoint administrative reconciliation identity conflicts with durable state") checkpointSessionPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$`) checkpointRevisionPattern = regexp.MustCompile(`^(?:0|rev_[0-9]+)$`) - checkpointEventCursorPattern = regexp.MustCompile(`^(?:0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,501})$`) + checkpointEventCursorPattern = regexp.MustCompile(`^(?:0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,500})$`) ) const ( diff --git a/internal/relayfile/checkpoint_seal_test.go b/internal/relayfile/checkpoint_seal_test.go index 7ca25175..378a5e09 100644 --- a/internal/relayfile/checkpoint_seal_test.go +++ b/internal/relayfile/checkpoint_seal_test.go @@ -13,8 +13,8 @@ import ( const checkpointTestConsumerPrincipal = "cloud-dashboard-observer" func TestCheckpointEventCursorPattern(t *testing.T) { - valid := []string{"0", "evt_42", "upstream:v1:github:pull_123", "upstream:v1:github:pull_123:2", "upstream:v1:" + strings.Repeat("a", 501)} - invalid := []string{"", " ", "evt_", "upstream:v1:", "upstream:v1:github pull_123", " upstream:v1:github:pull_123 ", "upstream:v1:github\tpull_123", "upstream:v1:slack:bad\\id", "upstream:v1:slack:bad\x7fid", "upstream:v1:" + strings.Repeat("a", 502)} + valid := []string{"0", "evt_42", "upstream:v1:github:pull_123", "upstream:v1:github:pull_123:2", "upstream:v1:" + strings.Repeat("a", 500)} + invalid := []string{"", " ", "evt_", "upstream:v1:", "upstream:v1:github pull_123", " upstream:v1:github:pull_123 ", "upstream:v1:github\tpull_123", "upstream:v1:slack:bad\\id", "upstream:v1:slack:bad\x7fid", "upstream:v1:" + strings.Repeat("a", 501)} for _, cursor := range valid { if !checkpointEventCursorPattern.MatchString(cursor) { t.Errorf("valid cursor rejected: %q", cursor) diff --git a/openapi/relayfile-v1.openapi.yaml b/openapi/relayfile-v1.openapi.yaml index f83843e6..5780b13a 100644 --- a/openapi/relayfile-v1.openapi.yaml +++ b/openapi/relayfile-v1.openapi.yaml @@ -4121,7 +4121,7 @@ components: pattern: '^(0|rev_[0-9]+)$' eventCursor: type: string - pattern: '^(0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,501})$' + pattern: '^(0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,500})$' issuedAt: type: string format: date-time @@ -4219,7 +4219,7 @@ components: pattern: '^(0|rev_[0-9]+)$' eventCursor: type: string - pattern: '^(0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,501})$' + pattern: '^(0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,500})$' consumedAt: type: string format: date-time @@ -4262,7 +4262,7 @@ components: pattern: '^(0|rev_[0-9]+)$' eventCursor: type: string - pattern: '^(0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,501})$' + pattern: '^(0|evt_[0-9]+|upstream:v1:[A-Za-z0-9._:\-]{1,500})$' issuedAt: type: string format: date-time