From a02547aefb5712d634356c52453925f1c9cda163 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 15:43:35 +0800 Subject: [PATCH 01/21] refactor: retire release acceptance API key leases --- .../scripts/test_model_context_capacity.sh | 4 +- .github/workflows/downstream-verify.yml | 7 +- backend/cmd/server/main.go | 55 ------- backend/cmd/server/main_test.go | 54 ------- backend/ent/apikey.go | 27 +--- backend/ent/apikey/apikey.go | 22 --- backend/ent/apikey/where.go | 150 ----------------- backend/ent/apikey_create.go | 153 ------------------ backend/ent/apikey_update.go | 106 ------------ backend/ent/migrate/schema.go | 26 +-- backend/ent/mutation.go | 129 +-------------- backend/ent/runtime/runtime.go | 26 +-- backend/ent/schema/api_key.go | 12 -- backend/internal/handler/dto/mappers.go | 4 - backend/internal/handler/dto/types.go | 5 - backend/internal/repository/api_key_repo.go | 64 ++------ .../api_key_repo_integration_test.go | 60 ------- .../service/admin_service_apikey_test.go | 27 ---- backend/internal/service/admin_user.go | 13 +- backend/internal/service/api_key.go | 5 - .../service/openai_codex_context_contract.go | 135 ---------------- .../openai_codex_context_contract_test.go | 68 -------- .../274_purge_release_acceptance_api_keys.sql | 73 +++++++++ ...acceptance_api_key_lease_migration_test.go | 25 --- ...e_retirement_migration_integration_test.go | 138 ++++++++++++++++ .../admin/user/UserApiKeysModal.vue | 14 +- .../src/i18n/locales/en/admin/overview.ts | 2 - .../src/i18n/locales/zh/admin/overview.ts | 2 - 28 files changed, 252 insertions(+), 1154 deletions(-) delete mode 100644 backend/cmd/server/main_test.go delete mode 100644 backend/internal/service/openai_codex_context_contract.go delete mode 100644 backend/internal/service/openai_codex_context_contract_test.go create mode 100644 backend/migrations/274_purge_release_acceptance_api_keys.sql delete mode 100644 backend/migrations/release_acceptance_api_key_lease_migration_test.go create mode 100644 backend/migrations/release_acceptance_retirement_migration_integration_test.go diff --git a/.github/scripts/test_model_context_capacity.sh b/.github/scripts/test_model_context_capacity.sh index 4825b053ed2a..712770c55f51 100644 --- a/.github/scripts/test_model_context_capacity.sh +++ b/.github/scripts/test_model_context_capacity.sh @@ -6,6 +6,6 @@ cd "$repo_root/backend" # Offline policy, persistence, and wire-contract fixtures only; no model calls. go test -p=1 -tags unit \ - ./internal/service ./internal/repository ./internal/handler ./internal/handler/admin ./cmd/server \ - -run 'Test.*(ModelContext|OfficialModelCatalog|ContextCapacit|GroupModelCapacity|CodexCapacityProjection|SyncUpstreamModelCatalog.*Capacity|RunCodexContextContractVerification)' \ + ./internal/service ./internal/repository ./internal/handler ./internal/handler/admin \ + -run 'Test.*(ModelContext|OfficialModelCatalog|ContextCapacit|GroupModelCapacity|CodexCapacityProjection|SyncUpstreamModelCatalog.*Capacity)' \ -count=1 diff --git a/.github/workflows/downstream-verify.yml b/.github/workflows/downstream-verify.yml index 09ab20dcb0b3..c3fedebae90f 100644 --- a/.github/workflows/downstream-verify.yml +++ b/.github/workflows/downstream-verify.yml @@ -55,7 +55,7 @@ jobs: working-directory: backend run: | go test -p=1 -tags unit ./internal/repository ./internal/service ./internal/handler ./internal/handler/admin -run 'Test.*(CodexImageGenerationBridgeOverridePrecedence|TurnStateCommits|SchedulerCache|GatewayModels|WriteOpenAIModelsList|AccountHandlerGetAvailableModels|ForwardResponsesOllamaClampPreservesContinuationPolicy|AccountAvailableModels|FetchOpenAIAccountModels|SetAnthropicAPIKeyAuthHeader|OllamaCloud.*(MaxTokens|MaxOutputTokens|Bearer)|Clamps.*OllamaBase)' -count=1 - go test -p=1 -tags unit ./migrations -run 'Test.*(Migration222|Migration223|Migration224|Migration230|Migration231|Migration232|Migration235|Migration236|GroupModelAllowlistRepairMigration|ReleaseAcceptance)' -count=1 + go test -p=1 -tags unit ./migrations -run 'Test.*(Migration222|Migration223|Migration224|Migration230|Migration231|Migration232|Migration235|Migration236|GroupModelAllowlistRepairMigration)' -count=1 - name: Request body recovery tests working-directory: backend run: go test -p=1 ./internal/pkg/httputil ./internal/handler -run 'Test(ReadRequestBodyWithPrealloc|ReadLenientJSONRequestBodyWithPrealloc|RequestBodyReadDiagnostics|ClassifyRequestContentEncoding)' -count=1 @@ -71,7 +71,10 @@ jobs: run: go test -p=1 -tags unit ./internal/handler/admin -run '^TestAccountJobBulk.*$' -count=1 - name: Account taxonomy migration integration test working-directory: backend - run: go test -p=1 -tags integration ./internal/repository -run '^Test(AccountTaxonomy.*|DeleteAccountFolder.*)Integration$|^TestAPIKeyRepoSuite$/^TestReleaseAcceptanceKeyIsAdminListedReadOnlyAndAuthenticates$' -count=1 + run: go test -p=1 -tags integration ./internal/repository -run '^Test(AccountTaxonomy.*|DeleteAccountFolder.*)Integration$' -count=1 + - name: Release acceptance retirement migration integration test + working-directory: backend + run: go test -p=1 -tags integration ./migrations -run '^TestMigration274RemovesReleaseAcceptanceKeysSafely$' -count=1 - name: Repository audit integration tests working-directory: backend run: go test -p=1 -tags integration ./internal/repository -run '^Test(PGXBatchInsertAuditAndSystemLogs|Migration236.*)$' -count=1 diff --git a/backend/cmd/server/main.go b/backend/cmd/server/main.go index 9caac8fe13b7..d34868803cc8 100644 --- a/backend/cmd/server/main.go +++ b/backend/cmd/server/main.go @@ -7,8 +7,6 @@ import ( _ "embed" "errors" "flag" - "fmt" - "io" "log" "net/http" "os" @@ -22,7 +20,6 @@ import ( "github.com/Wei-Shaw/sub2api/internal/handler" "github.com/Wei-Shaw/sub2api/internal/pkg/logger" "github.com/Wei-Shaw/sub2api/internal/server/middleware" - "github.com/Wei-Shaw/sub2api/internal/service" "github.com/Wei-Shaw/sub2api/internal/setup" "github.com/Wei-Shaw/sub2api/internal/web" @@ -62,24 +59,7 @@ func main() { // Parse command line flags setupMode := flag.Bool("setup", false, "Run setup wizard in CLI mode") showVersion := flag.Bool("version", false, "Show version information") - verifyCodexContextContract := flag.Bool( - "verify-codex-context-contract", - false, - "Verify ordinary-provider context capacity priority and protected-manifest contracts offline", - ) flag.Parse() - if *verifyCodexContextContract { - exitCode := runCodexContextContractVerification( - os.Stdout, - *setupMode, - *showVersion, - flag.Args(), - ) - if exitCode != 0 { - os.Exit(exitCode) - } - return - } if *showVersion { log.Printf("Sub2API %s (commit: %s, built: %s)\n", Version, Commit, Date) @@ -114,41 +94,6 @@ func main() { runMainServer() } -func runCodexContextContractVerification( - stdout io.Writer, - setupMode bool, - showVersion bool, - positionalArgs []string, -) int { - return runCodexContextContractVerificationWith( - stdout, - setupMode, - showVersion, - positionalArgs, - service.VerifyOfficialCodexContextContract, - ) -} - -func runCodexContextContractVerificationWith( - stdout io.Writer, - setupMode bool, - showVersion bool, - positionalArgs []string, - verify func() (string, error), -) int { - if setupMode || showVersion || len(positionalArgs) != 0 { - _, _ = fmt.Fprintln(stdout, service.OfficialCodexContextInvalidArgsLine) - return 2 - } - line, err := verify() - if err != nil { - _, _ = fmt.Fprintln(stdout, service.OfficialCodexContextContractFailureLine) - return 1 - } - _, _ = fmt.Fprintln(stdout, line) - return 0 -} - func runSetupServer() { r := gin.New() r.Use(middleware.Recovery()) diff --git a/backend/cmd/server/main_test.go b/backend/cmd/server/main_test.go deleted file mode 100644 index 2544082e28fb..000000000000 --- a/backend/cmd/server/main_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "bytes" - "errors" - "testing" - - "github.com/Wei-Shaw/sub2api/internal/service" - "github.com/stretchr/testify/require" -) - -func TestRunCodexContextContractVerification(t *testing.T) { - var output bytes.Buffer - require.Equal(t, 0, runCodexContextContractVerification(&output, false, false, nil)) - require.Equal(t, service.OfficialCodexContextContractSuccessLine+"\n", output.String()) -} - -func TestRunCodexContextContractVerificationFailsWithFixedShape(t *testing.T) { - var output bytes.Buffer - exitCode := runCodexContextContractVerificationWith( - &output, - false, - false, - nil, - func() (string, error) { return "sensitive-detail", errors.New("sensitive-detail") }, - ) - require.Equal(t, 1, exitCode) - require.Equal(t, service.OfficialCodexContextContractFailureLine+"\n", output.String()) - require.NotContains(t, output.String(), "sensitive-detail") -} - -func TestRunCodexContextContractVerificationRejectsConflictingArguments(t *testing.T) { - tests := []struct { - name string - setup, version bool - args []string - }{ - {name: "setup", setup: true}, - {name: "version", version: true}, - {name: "positional", args: []string{"unexpected"}}, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - var output bytes.Buffer - require.Equal(t, 2, runCodexContextContractVerification( - &output, - test.setup, - test.version, - test.args, - )) - require.Equal(t, service.OfficialCodexContextInvalidArgsLine+"\n", output.String()) - }) - } -} diff --git a/backend/ent/apikey.go b/backend/ent/apikey.go index c9774b9ef630..9ee660c2da69 100644 --- a/backend/ent/apikey.go +++ b/backend/ent/apikey.go @@ -36,10 +36,6 @@ type APIKey struct { GroupID *int64 `json:"group_id,omitempty"` // Status holds the value of the "status" field. Status string `json:"status,omitempty"` - // Internal lifecycle purpose; user keys remain the public default - Purpose string `json:"purpose,omitempty"` - // Opaque idempotency identifier for short-lived internal leases - LeaseID *string `json:"lease_id,omitempty"` // Last usage time of this API key LastUsedAt *time.Time `json:"last_used_at,omitempty"` // Allowed IPs/CIDRs, e.g. ["192.168.1.100", "10.0.0.0/8"] @@ -131,7 +127,7 @@ func (*APIKey) scanValues(columns []string) ([]any, error) { values[i] = new(sql.NullFloat64) case apikey.FieldID, apikey.FieldUserID, apikey.FieldGroupID: values[i] = new(sql.NullInt64) - case apikey.FieldKey, apikey.FieldName, apikey.FieldStatus, apikey.FieldPurpose, apikey.FieldLeaseID: + case apikey.FieldKey, apikey.FieldName, apikey.FieldStatus: values[i] = new(sql.NullString) case apikey.FieldCreatedAt, apikey.FieldUpdatedAt, apikey.FieldDeletedAt, apikey.FieldLastUsedAt, apikey.FieldExpiresAt, apikey.FieldWindow5hStart, apikey.FieldWindow1dStart, apikey.FieldWindow7dStart: values[i] = new(sql.NullTime) @@ -206,19 +202,6 @@ func (_m *APIKey) assignValues(columns []string, values []any) error { } else if value.Valid { _m.Status = value.String } - case apikey.FieldPurpose: - if value, ok := values[i].(*sql.NullString); !ok { - return fmt.Errorf("unexpected type %T for field purpose", values[i]) - } else if value.Valid { - _m.Purpose = value.String - } - case apikey.FieldLeaseID: - if value, ok := values[i].(*sql.NullString); !ok { - return fmt.Errorf("unexpected type %T for field lease_id", values[i]) - } else if value.Valid { - _m.LeaseID = new(string) - *_m.LeaseID = value.String - } case apikey.FieldLastUsedAt: if value, ok := values[i].(*sql.NullTime); !ok { return fmt.Errorf("unexpected type %T for field last_used_at", values[i]) @@ -397,14 +380,6 @@ func (_m *APIKey) String() string { builder.WriteString("status=") builder.WriteString(_m.Status) builder.WriteString(", ") - builder.WriteString("purpose=") - builder.WriteString(_m.Purpose) - builder.WriteString(", ") - if v := _m.LeaseID; v != nil { - builder.WriteString("lease_id=") - builder.WriteString(*v) - } - builder.WriteString(", ") if v := _m.LastUsedAt; v != nil { builder.WriteString("last_used_at=") builder.WriteString(v.Format(time.ANSIC)) diff --git a/backend/ent/apikey/apikey.go b/backend/ent/apikey/apikey.go index 5e08424c74aa..d398a027b867 100644 --- a/backend/ent/apikey/apikey.go +++ b/backend/ent/apikey/apikey.go @@ -31,10 +31,6 @@ const ( FieldGroupID = "group_id" // FieldStatus holds the string denoting the status field in the database. FieldStatus = "status" - // FieldPurpose holds the string denoting the purpose field in the database. - FieldPurpose = "purpose" - // FieldLeaseID holds the string denoting the lease_id field in the database. - FieldLeaseID = "lease_id" // FieldLastUsedAt holds the string denoting the last_used_at field in the database. FieldLastUsedAt = "last_used_at" // FieldIPWhitelist holds the string denoting the ip_whitelist field in the database. @@ -107,8 +103,6 @@ var Columns = []string{ FieldName, FieldGroupID, FieldStatus, - FieldPurpose, - FieldLeaseID, FieldLastUsedAt, FieldIPWhitelist, FieldIPBlacklist, @@ -158,12 +152,6 @@ var ( DefaultStatus string // StatusValidator is a validator for the "status" field. It is called by the builders before save. StatusValidator func(string) error - // DefaultPurpose holds the default value on creation for the "purpose" field. - DefaultPurpose string - // PurposeValidator is a validator for the "purpose" field. It is called by the builders before save. - PurposeValidator func(string) error - // LeaseIDValidator is a validator for the "lease_id" field. It is called by the builders before save. - LeaseIDValidator func(string) error // DefaultQuota holds the default value on creation for the "quota" field. DefaultQuota float64 // DefaultQuotaUsed holds the default value on creation for the "quota_used" field. @@ -230,16 +218,6 @@ func ByStatus(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldStatus, opts...).ToFunc() } -// ByPurpose orders the results by the purpose field. -func ByPurpose(opts ...sql.OrderTermOption) OrderOption { - return sql.OrderByField(FieldPurpose, opts...).ToFunc() -} - -// ByLeaseID orders the results by the lease_id field. -func ByLeaseID(opts ...sql.OrderTermOption) OrderOption { - return sql.OrderByField(FieldLeaseID, opts...).ToFunc() -} - // ByLastUsedAt orders the results by the last_used_at field. func ByLastUsedAt(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldLastUsedAt, opts...).ToFunc() diff --git a/backend/ent/apikey/where.go b/backend/ent/apikey/where.go index fcafdf837eaf..edd2652baaed 100644 --- a/backend/ent/apikey/where.go +++ b/backend/ent/apikey/where.go @@ -95,16 +95,6 @@ func Status(v string) predicate.APIKey { return predicate.APIKey(sql.FieldEQ(FieldStatus, v)) } -// Purpose applies equality check predicate on the "purpose" field. It's identical to PurposeEQ. -func Purpose(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldEQ(FieldPurpose, v)) -} - -// LeaseID applies equality check predicate on the "lease_id" field. It's identical to LeaseIDEQ. -func LeaseID(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldEQ(FieldLeaseID, v)) -} - // LastUsedAt applies equality check predicate on the "last_used_at" field. It's identical to LastUsedAtEQ. func LastUsedAt(v time.Time) predicate.APIKey { return predicate.APIKey(sql.FieldEQ(FieldLastUsedAt, v)) @@ -545,146 +535,6 @@ func StatusContainsFold(v string) predicate.APIKey { return predicate.APIKey(sql.FieldContainsFold(FieldStatus, v)) } -// PurposeEQ applies the EQ predicate on the "purpose" field. -func PurposeEQ(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldEQ(FieldPurpose, v)) -} - -// PurposeNEQ applies the NEQ predicate on the "purpose" field. -func PurposeNEQ(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldNEQ(FieldPurpose, v)) -} - -// PurposeIn applies the In predicate on the "purpose" field. -func PurposeIn(vs ...string) predicate.APIKey { - return predicate.APIKey(sql.FieldIn(FieldPurpose, vs...)) -} - -// PurposeNotIn applies the NotIn predicate on the "purpose" field. -func PurposeNotIn(vs ...string) predicate.APIKey { - return predicate.APIKey(sql.FieldNotIn(FieldPurpose, vs...)) -} - -// PurposeGT applies the GT predicate on the "purpose" field. -func PurposeGT(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldGT(FieldPurpose, v)) -} - -// PurposeGTE applies the GTE predicate on the "purpose" field. -func PurposeGTE(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldGTE(FieldPurpose, v)) -} - -// PurposeLT applies the LT predicate on the "purpose" field. -func PurposeLT(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldLT(FieldPurpose, v)) -} - -// PurposeLTE applies the LTE predicate on the "purpose" field. -func PurposeLTE(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldLTE(FieldPurpose, v)) -} - -// PurposeContains applies the Contains predicate on the "purpose" field. -func PurposeContains(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldContains(FieldPurpose, v)) -} - -// PurposeHasPrefix applies the HasPrefix predicate on the "purpose" field. -func PurposeHasPrefix(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldHasPrefix(FieldPurpose, v)) -} - -// PurposeHasSuffix applies the HasSuffix predicate on the "purpose" field. -func PurposeHasSuffix(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldHasSuffix(FieldPurpose, v)) -} - -// PurposeEqualFold applies the EqualFold predicate on the "purpose" field. -func PurposeEqualFold(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldEqualFold(FieldPurpose, v)) -} - -// PurposeContainsFold applies the ContainsFold predicate on the "purpose" field. -func PurposeContainsFold(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldContainsFold(FieldPurpose, v)) -} - -// LeaseIDEQ applies the EQ predicate on the "lease_id" field. -func LeaseIDEQ(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldEQ(FieldLeaseID, v)) -} - -// LeaseIDNEQ applies the NEQ predicate on the "lease_id" field. -func LeaseIDNEQ(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldNEQ(FieldLeaseID, v)) -} - -// LeaseIDIn applies the In predicate on the "lease_id" field. -func LeaseIDIn(vs ...string) predicate.APIKey { - return predicate.APIKey(sql.FieldIn(FieldLeaseID, vs...)) -} - -// LeaseIDNotIn applies the NotIn predicate on the "lease_id" field. -func LeaseIDNotIn(vs ...string) predicate.APIKey { - return predicate.APIKey(sql.FieldNotIn(FieldLeaseID, vs...)) -} - -// LeaseIDGT applies the GT predicate on the "lease_id" field. -func LeaseIDGT(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldGT(FieldLeaseID, v)) -} - -// LeaseIDGTE applies the GTE predicate on the "lease_id" field. -func LeaseIDGTE(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldGTE(FieldLeaseID, v)) -} - -// LeaseIDLT applies the LT predicate on the "lease_id" field. -func LeaseIDLT(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldLT(FieldLeaseID, v)) -} - -// LeaseIDLTE applies the LTE predicate on the "lease_id" field. -func LeaseIDLTE(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldLTE(FieldLeaseID, v)) -} - -// LeaseIDContains applies the Contains predicate on the "lease_id" field. -func LeaseIDContains(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldContains(FieldLeaseID, v)) -} - -// LeaseIDHasPrefix applies the HasPrefix predicate on the "lease_id" field. -func LeaseIDHasPrefix(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldHasPrefix(FieldLeaseID, v)) -} - -// LeaseIDHasSuffix applies the HasSuffix predicate on the "lease_id" field. -func LeaseIDHasSuffix(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldHasSuffix(FieldLeaseID, v)) -} - -// LeaseIDIsNil applies the IsNil predicate on the "lease_id" field. -func LeaseIDIsNil() predicate.APIKey { - return predicate.APIKey(sql.FieldIsNull(FieldLeaseID)) -} - -// LeaseIDNotNil applies the NotNil predicate on the "lease_id" field. -func LeaseIDNotNil() predicate.APIKey { - return predicate.APIKey(sql.FieldNotNull(FieldLeaseID)) -} - -// LeaseIDEqualFold applies the EqualFold predicate on the "lease_id" field. -func LeaseIDEqualFold(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldEqualFold(FieldLeaseID, v)) -} - -// LeaseIDContainsFold applies the ContainsFold predicate on the "lease_id" field. -func LeaseIDContainsFold(v string) predicate.APIKey { - return predicate.APIKey(sql.FieldContainsFold(FieldLeaseID, v)) -} - // LastUsedAtEQ applies the EQ predicate on the "last_used_at" field. func LastUsedAtEQ(v time.Time) predicate.APIKey { return predicate.APIKey(sql.FieldEQ(FieldLastUsedAt, v)) diff --git a/backend/ent/apikey_create.go b/backend/ent/apikey_create.go index 44015d0f729e..4ec8aeaae4e3 100644 --- a/backend/ent/apikey_create.go +++ b/backend/ent/apikey_create.go @@ -113,34 +113,6 @@ func (_c *APIKeyCreate) SetNillableStatus(v *string) *APIKeyCreate { return _c } -// SetPurpose sets the "purpose" field. -func (_c *APIKeyCreate) SetPurpose(v string) *APIKeyCreate { - _c.mutation.SetPurpose(v) - return _c -} - -// SetNillablePurpose sets the "purpose" field if the given value is not nil. -func (_c *APIKeyCreate) SetNillablePurpose(v *string) *APIKeyCreate { - if v != nil { - _c.SetPurpose(*v) - } - return _c -} - -// SetLeaseID sets the "lease_id" field. -func (_c *APIKeyCreate) SetLeaseID(v string) *APIKeyCreate { - _c.mutation.SetLeaseID(v) - return _c -} - -// SetNillableLeaseID sets the "lease_id" field if the given value is not nil. -func (_c *APIKeyCreate) SetNillableLeaseID(v *string) *APIKeyCreate { - if v != nil { - _c.SetLeaseID(*v) - } - return _c -} - // SetLastUsedAt sets the "last_used_at" field. func (_c *APIKeyCreate) SetLastUsedAt(v time.Time) *APIKeyCreate { _c.mutation.SetLastUsedAt(v) @@ -415,10 +387,6 @@ func (_c *APIKeyCreate) defaults() error { v := apikey.DefaultStatus _c.mutation.SetStatus(v) } - if _, ok := _c.mutation.Purpose(); !ok { - v := apikey.DefaultPurpose - _c.mutation.SetPurpose(v) - } if _, ok := _c.mutation.Quota(); !ok { v := apikey.DefaultQuota _c.mutation.SetQuota(v) @@ -489,19 +457,6 @@ func (_c *APIKeyCreate) check() error { return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)} } } - if _, ok := _c.mutation.Purpose(); !ok { - return &ValidationError{Name: "purpose", err: errors.New(`ent: missing required field "APIKey.purpose"`)} - } - if v, ok := _c.mutation.Purpose(); ok { - if err := apikey.PurposeValidator(v); err != nil { - return &ValidationError{Name: "purpose", err: fmt.Errorf(`ent: validator failed for field "APIKey.purpose": %w`, err)} - } - } - if v, ok := _c.mutation.LeaseID(); ok { - if err := apikey.LeaseIDValidator(v); err != nil { - return &ValidationError{Name: "lease_id", err: fmt.Errorf(`ent: validator failed for field "APIKey.lease_id": %w`, err)} - } - } if _, ok := _c.mutation.Quota(); !ok { return &ValidationError{Name: "quota", err: errors.New(`ent: missing required field "APIKey.quota"`)} } @@ -580,14 +535,6 @@ func (_c *APIKeyCreate) createSpec() (*APIKey, *sqlgraph.CreateSpec) { _spec.SetField(apikey.FieldStatus, field.TypeString, value) _node.Status = value } - if value, ok := _c.mutation.Purpose(); ok { - _spec.SetField(apikey.FieldPurpose, field.TypeString, value) - _node.Purpose = value - } - if value, ok := _c.mutation.LeaseID(); ok { - _spec.SetField(apikey.FieldLeaseID, field.TypeString, value) - _node.LeaseID = &value - } if value, ok := _c.mutation.LastUsedAt(); ok { _spec.SetField(apikey.FieldLastUsedAt, field.TypeTime, value) _node.LastUsedAt = &value @@ -846,36 +793,6 @@ func (u *APIKeyUpsert) UpdateStatus() *APIKeyUpsert { return u } -// SetPurpose sets the "purpose" field. -func (u *APIKeyUpsert) SetPurpose(v string) *APIKeyUpsert { - u.Set(apikey.FieldPurpose, v) - return u -} - -// UpdatePurpose sets the "purpose" field to the value that was provided on create. -func (u *APIKeyUpsert) UpdatePurpose() *APIKeyUpsert { - u.SetExcluded(apikey.FieldPurpose) - return u -} - -// SetLeaseID sets the "lease_id" field. -func (u *APIKeyUpsert) SetLeaseID(v string) *APIKeyUpsert { - u.Set(apikey.FieldLeaseID, v) - return u -} - -// UpdateLeaseID sets the "lease_id" field to the value that was provided on create. -func (u *APIKeyUpsert) UpdateLeaseID() *APIKeyUpsert { - u.SetExcluded(apikey.FieldLeaseID) - return u -} - -// ClearLeaseID clears the value of the "lease_id" field. -func (u *APIKeyUpsert) ClearLeaseID() *APIKeyUpsert { - u.SetNull(apikey.FieldLeaseID) - return u -} - // SetLastUsedAt sets the "last_used_at" field. func (u *APIKeyUpsert) SetLastUsedAt(v time.Time) *APIKeyUpsert { u.Set(apikey.FieldLastUsedAt, v) @@ -1303,41 +1220,6 @@ func (u *APIKeyUpsertOne) UpdateStatus() *APIKeyUpsertOne { }) } -// SetPurpose sets the "purpose" field. -func (u *APIKeyUpsertOne) SetPurpose(v string) *APIKeyUpsertOne { - return u.Update(func(s *APIKeyUpsert) { - s.SetPurpose(v) - }) -} - -// UpdatePurpose sets the "purpose" field to the value that was provided on create. -func (u *APIKeyUpsertOne) UpdatePurpose() *APIKeyUpsertOne { - return u.Update(func(s *APIKeyUpsert) { - s.UpdatePurpose() - }) -} - -// SetLeaseID sets the "lease_id" field. -func (u *APIKeyUpsertOne) SetLeaseID(v string) *APIKeyUpsertOne { - return u.Update(func(s *APIKeyUpsert) { - s.SetLeaseID(v) - }) -} - -// UpdateLeaseID sets the "lease_id" field to the value that was provided on create. -func (u *APIKeyUpsertOne) UpdateLeaseID() *APIKeyUpsertOne { - return u.Update(func(s *APIKeyUpsert) { - s.UpdateLeaseID() - }) -} - -// ClearLeaseID clears the value of the "lease_id" field. -func (u *APIKeyUpsertOne) ClearLeaseID() *APIKeyUpsertOne { - return u.Update(func(s *APIKeyUpsert) { - s.ClearLeaseID() - }) -} - // SetLastUsedAt sets the "last_used_at" field. func (u *APIKeyUpsertOne) SetLastUsedAt(v time.Time) *APIKeyUpsertOne { return u.Update(func(s *APIKeyUpsert) { @@ -1976,41 +1858,6 @@ func (u *APIKeyUpsertBulk) UpdateStatus() *APIKeyUpsertBulk { }) } -// SetPurpose sets the "purpose" field. -func (u *APIKeyUpsertBulk) SetPurpose(v string) *APIKeyUpsertBulk { - return u.Update(func(s *APIKeyUpsert) { - s.SetPurpose(v) - }) -} - -// UpdatePurpose sets the "purpose" field to the value that was provided on create. -func (u *APIKeyUpsertBulk) UpdatePurpose() *APIKeyUpsertBulk { - return u.Update(func(s *APIKeyUpsert) { - s.UpdatePurpose() - }) -} - -// SetLeaseID sets the "lease_id" field. -func (u *APIKeyUpsertBulk) SetLeaseID(v string) *APIKeyUpsertBulk { - return u.Update(func(s *APIKeyUpsert) { - s.SetLeaseID(v) - }) -} - -// UpdateLeaseID sets the "lease_id" field to the value that was provided on create. -func (u *APIKeyUpsertBulk) UpdateLeaseID() *APIKeyUpsertBulk { - return u.Update(func(s *APIKeyUpsert) { - s.UpdateLeaseID() - }) -} - -// ClearLeaseID clears the value of the "lease_id" field. -func (u *APIKeyUpsertBulk) ClearLeaseID() *APIKeyUpsertBulk { - return u.Update(func(s *APIKeyUpsert) { - s.ClearLeaseID() - }) -} - // SetLastUsedAt sets the "last_used_at" field. func (u *APIKeyUpsertBulk) SetLastUsedAt(v time.Time) *APIKeyUpsertBulk { return u.Update(func(s *APIKeyUpsert) { diff --git a/backend/ent/apikey_update.go b/backend/ent/apikey_update.go index 6f586fc72dc3..db341e4c9d53 100644 --- a/backend/ent/apikey_update.go +++ b/backend/ent/apikey_update.go @@ -134,40 +134,6 @@ func (_u *APIKeyUpdate) SetNillableStatus(v *string) *APIKeyUpdate { return _u } -// SetPurpose sets the "purpose" field. -func (_u *APIKeyUpdate) SetPurpose(v string) *APIKeyUpdate { - _u.mutation.SetPurpose(v) - return _u -} - -// SetNillablePurpose sets the "purpose" field if the given value is not nil. -func (_u *APIKeyUpdate) SetNillablePurpose(v *string) *APIKeyUpdate { - if v != nil { - _u.SetPurpose(*v) - } - return _u -} - -// SetLeaseID sets the "lease_id" field. -func (_u *APIKeyUpdate) SetLeaseID(v string) *APIKeyUpdate { - _u.mutation.SetLeaseID(v) - return _u -} - -// SetNillableLeaseID sets the "lease_id" field if the given value is not nil. -func (_u *APIKeyUpdate) SetNillableLeaseID(v *string) *APIKeyUpdate { - if v != nil { - _u.SetLeaseID(*v) - } - return _u -} - -// ClearLeaseID clears the value of the "lease_id" field. -func (_u *APIKeyUpdate) ClearLeaseID() *APIKeyUpdate { - _u.mutation.ClearLeaseID() - return _u -} - // SetLastUsedAt sets the "last_used_at" field. func (_u *APIKeyUpdate) SetLastUsedAt(v time.Time) *APIKeyUpdate { _u.mutation.SetLastUsedAt(v) @@ -594,16 +560,6 @@ func (_u *APIKeyUpdate) check() error { return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)} } } - if v, ok := _u.mutation.Purpose(); ok { - if err := apikey.PurposeValidator(v); err != nil { - return &ValidationError{Name: "purpose", err: fmt.Errorf(`ent: validator failed for field "APIKey.purpose": %w`, err)} - } - } - if v, ok := _u.mutation.LeaseID(); ok { - if err := apikey.LeaseIDValidator(v); err != nil { - return &ValidationError{Name: "lease_id", err: fmt.Errorf(`ent: validator failed for field "APIKey.lease_id": %w`, err)} - } - } if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 { return errors.New(`ent: clearing a required unique edge "APIKey.user"`) } @@ -640,15 +596,6 @@ func (_u *APIKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) { if value, ok := _u.mutation.Status(); ok { _spec.SetField(apikey.FieldStatus, field.TypeString, value) } - if value, ok := _u.mutation.Purpose(); ok { - _spec.SetField(apikey.FieldPurpose, field.TypeString, value) - } - if value, ok := _u.mutation.LeaseID(); ok { - _spec.SetField(apikey.FieldLeaseID, field.TypeString, value) - } - if _u.mutation.LeaseIDCleared() { - _spec.ClearField(apikey.FieldLeaseID, field.TypeString) - } if value, ok := _u.mutation.LastUsedAt(); ok { _spec.SetField(apikey.FieldLastUsedAt, field.TypeTime, value) } @@ -974,40 +921,6 @@ func (_u *APIKeyUpdateOne) SetNillableStatus(v *string) *APIKeyUpdateOne { return _u } -// SetPurpose sets the "purpose" field. -func (_u *APIKeyUpdateOne) SetPurpose(v string) *APIKeyUpdateOne { - _u.mutation.SetPurpose(v) - return _u -} - -// SetNillablePurpose sets the "purpose" field if the given value is not nil. -func (_u *APIKeyUpdateOne) SetNillablePurpose(v *string) *APIKeyUpdateOne { - if v != nil { - _u.SetPurpose(*v) - } - return _u -} - -// SetLeaseID sets the "lease_id" field. -func (_u *APIKeyUpdateOne) SetLeaseID(v string) *APIKeyUpdateOne { - _u.mutation.SetLeaseID(v) - return _u -} - -// SetNillableLeaseID sets the "lease_id" field if the given value is not nil. -func (_u *APIKeyUpdateOne) SetNillableLeaseID(v *string) *APIKeyUpdateOne { - if v != nil { - _u.SetLeaseID(*v) - } - return _u -} - -// ClearLeaseID clears the value of the "lease_id" field. -func (_u *APIKeyUpdateOne) ClearLeaseID() *APIKeyUpdateOne { - _u.mutation.ClearLeaseID() - return _u -} - // SetLastUsedAt sets the "last_used_at" field. func (_u *APIKeyUpdateOne) SetLastUsedAt(v time.Time) *APIKeyUpdateOne { _u.mutation.SetLastUsedAt(v) @@ -1447,16 +1360,6 @@ func (_u *APIKeyUpdateOne) check() error { return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)} } } - if v, ok := _u.mutation.Purpose(); ok { - if err := apikey.PurposeValidator(v); err != nil { - return &ValidationError{Name: "purpose", err: fmt.Errorf(`ent: validator failed for field "APIKey.purpose": %w`, err)} - } - } - if v, ok := _u.mutation.LeaseID(); ok { - if err := apikey.LeaseIDValidator(v); err != nil { - return &ValidationError{Name: "lease_id", err: fmt.Errorf(`ent: validator failed for field "APIKey.lease_id": %w`, err)} - } - } if _u.mutation.UserCleared() && len(_u.mutation.UserIDs()) > 0 { return errors.New(`ent: clearing a required unique edge "APIKey.user"`) } @@ -1510,15 +1413,6 @@ func (_u *APIKeyUpdateOne) sqlSave(ctx context.Context) (_node *APIKey, err erro if value, ok := _u.mutation.Status(); ok { _spec.SetField(apikey.FieldStatus, field.TypeString, value) } - if value, ok := _u.mutation.Purpose(); ok { - _spec.SetField(apikey.FieldPurpose, field.TypeString, value) - } - if value, ok := _u.mutation.LeaseID(); ok { - _spec.SetField(apikey.FieldLeaseID, field.TypeString, value) - } - if _u.mutation.LeaseIDCleared() { - _spec.ClearField(apikey.FieldLeaseID, field.TypeString) - } if value, ok := _u.mutation.LastUsedAt(); ok { _spec.SetField(apikey.FieldLastUsedAt, field.TypeTime, value) } diff --git a/backend/ent/migrate/schema.go b/backend/ent/migrate/schema.go index fcf0d4fccb20..ab102c5c72fd 100644 --- a/backend/ent/migrate/schema.go +++ b/backend/ent/migrate/schema.go @@ -18,8 +18,6 @@ var ( {Name: "key", Type: field.TypeString, Unique: true, Size: 128}, {Name: "name", Type: field.TypeString, Size: 100}, {Name: "status", Type: field.TypeString, Size: 20, Default: "active"}, - {Name: "purpose", Type: field.TypeString, Size: 32, Default: "user"}, - {Name: "lease_id", Type: field.TypeString, Unique: true, Nullable: true, Size: 64}, {Name: "last_used_at", Type: field.TypeTime, Nullable: true}, {Name: "ip_whitelist", Type: field.TypeJSON, Nullable: true}, {Name: "ip_blacklist", Type: field.TypeJSON, Nullable: true}, @@ -46,13 +44,13 @@ var ( ForeignKeys: []*schema.ForeignKey{ { Symbol: "api_keys_groups_api_keys", - Columns: []*schema.Column{APIKeysColumns[24]}, + Columns: []*schema.Column{APIKeysColumns[22]}, RefColumns: []*schema.Column{GroupsColumns[0]}, OnDelete: schema.SetNull, }, { Symbol: "api_keys_users_api_keys", - Columns: []*schema.Column{APIKeysColumns[25]}, + Columns: []*schema.Column{APIKeysColumns[23]}, RefColumns: []*schema.Column{UsersColumns[0]}, OnDelete: schema.NoAction, }, @@ -61,28 +59,18 @@ var ( { Name: "apikey_user_id", Unique: false, - Columns: []*schema.Column{APIKeysColumns[25]}, + Columns: []*schema.Column{APIKeysColumns[23]}, }, { Name: "apikey_group_id", Unique: false, - Columns: []*schema.Column{APIKeysColumns[24]}, + Columns: []*schema.Column{APIKeysColumns[22]}, }, { Name: "apikey_status", Unique: false, Columns: []*schema.Column{APIKeysColumns[6]}, }, - { - Name: "apikey_purpose", - Unique: false, - Columns: []*schema.Column{APIKeysColumns[7]}, - }, - { - Name: "apikey_purpose_expires_at", - Unique: false, - Columns: []*schema.Column{APIKeysColumns[7], APIKeysColumns[14]}, - }, { Name: "apikey_deleted_at", Unique: false, @@ -91,17 +79,17 @@ var ( { Name: "apikey_last_used_at", Unique: false, - Columns: []*schema.Column{APIKeysColumns[9]}, + Columns: []*schema.Column{APIKeysColumns[7]}, }, { Name: "apikey_quota_quota_used", Unique: false, - Columns: []*schema.Column{APIKeysColumns[12], APIKeysColumns[13]}, + Columns: []*schema.Column{APIKeysColumns[10], APIKeysColumns[11]}, }, { Name: "apikey_expires_at", Unique: false, - Columns: []*schema.Column{APIKeysColumns[14]}, + Columns: []*schema.Column{APIKeysColumns[12]}, }, }, } diff --git a/backend/ent/mutation.go b/backend/ent/mutation.go index 54f37900af36..9283f899bb61 100644 --- a/backend/ent/mutation.go +++ b/backend/ent/mutation.go @@ -123,8 +123,6 @@ type APIKeyMutation struct { key *string name *string status *string - purpose *string - lease_id *string last_used_at *time.Time ip_whitelist *[]string appendip_whitelist []string @@ -575,91 +573,6 @@ func (m *APIKeyMutation) ResetStatus() { m.status = nil } -// SetPurpose sets the "purpose" field. -func (m *APIKeyMutation) SetPurpose(s string) { - m.purpose = &s -} - -// Purpose returns the value of the "purpose" field in the mutation. -func (m *APIKeyMutation) Purpose() (r string, exists bool) { - v := m.purpose - if v == nil { - return - } - return *v, true -} - -// OldPurpose returns the old "purpose" field's value of the APIKey entity. -// If the APIKey object wasn't provided to the builder, the object is fetched from the database. -// An error is returned if the mutation operation is not UpdateOne, or the database query fails. -func (m *APIKeyMutation) OldPurpose(ctx context.Context) (v string, err error) { - if !m.op.Is(OpUpdateOne) { - return v, errors.New("OldPurpose is only allowed on UpdateOne operations") - } - if m.id == nil || m.oldValue == nil { - return v, errors.New("OldPurpose requires an ID field in the mutation") - } - oldValue, err := m.oldValue(ctx) - if err != nil { - return v, fmt.Errorf("querying old value for OldPurpose: %w", err) - } - return oldValue.Purpose, nil -} - -// ResetPurpose resets all changes to the "purpose" field. -func (m *APIKeyMutation) ResetPurpose() { - m.purpose = nil -} - -// SetLeaseID sets the "lease_id" field. -func (m *APIKeyMutation) SetLeaseID(s string) { - m.lease_id = &s -} - -// LeaseID returns the value of the "lease_id" field in the mutation. -func (m *APIKeyMutation) LeaseID() (r string, exists bool) { - v := m.lease_id - if v == nil { - return - } - return *v, true -} - -// OldLeaseID returns the old "lease_id" field's value of the APIKey entity. -// If the APIKey object wasn't provided to the builder, the object is fetched from the database. -// An error is returned if the mutation operation is not UpdateOne, or the database query fails. -func (m *APIKeyMutation) OldLeaseID(ctx context.Context) (v *string, err error) { - if !m.op.Is(OpUpdateOne) { - return v, errors.New("OldLeaseID is only allowed on UpdateOne operations") - } - if m.id == nil || m.oldValue == nil { - return v, errors.New("OldLeaseID requires an ID field in the mutation") - } - oldValue, err := m.oldValue(ctx) - if err != nil { - return v, fmt.Errorf("querying old value for OldLeaseID: %w", err) - } - return oldValue.LeaseID, nil -} - -// ClearLeaseID clears the value of the "lease_id" field. -func (m *APIKeyMutation) ClearLeaseID() { - m.lease_id = nil - m.clearedFields[apikey.FieldLeaseID] = struct{}{} -} - -// LeaseIDCleared returns if the "lease_id" field was cleared in this mutation. -func (m *APIKeyMutation) LeaseIDCleared() bool { - _, ok := m.clearedFields[apikey.FieldLeaseID] - return ok -} - -// ResetLeaseID resets all changes to the "lease_id" field. -func (m *APIKeyMutation) ResetLeaseID() { - m.lease_id = nil - delete(m.clearedFields, apikey.FieldLeaseID) -} - // SetLastUsedAt sets the "last_used_at" field. func (m *APIKeyMutation) SetLastUsedAt(t time.Time) { m.last_used_at = &t @@ -1625,7 +1538,7 @@ func (m *APIKeyMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *APIKeyMutation) Fields() []string { - fields := make([]string, 0, 25) + fields := make([]string, 0, 23) if m.created_at != nil { fields = append(fields, apikey.FieldCreatedAt) } @@ -1650,12 +1563,6 @@ func (m *APIKeyMutation) Fields() []string { if m.status != nil { fields = append(fields, apikey.FieldStatus) } - if m.purpose != nil { - fields = append(fields, apikey.FieldPurpose) - } - if m.lease_id != nil { - fields = append(fields, apikey.FieldLeaseID) - } if m.last_used_at != nil { fields = append(fields, apikey.FieldLastUsedAt) } @@ -1725,10 +1632,6 @@ func (m *APIKeyMutation) Field(name string) (ent.Value, bool) { return m.GroupID() case apikey.FieldStatus: return m.Status() - case apikey.FieldPurpose: - return m.Purpose() - case apikey.FieldLeaseID: - return m.LeaseID() case apikey.FieldLastUsedAt: return m.LastUsedAt() case apikey.FieldIPWhitelist: @@ -1784,10 +1687,6 @@ func (m *APIKeyMutation) OldField(ctx context.Context, name string) (ent.Value, return m.OldGroupID(ctx) case apikey.FieldStatus: return m.OldStatus(ctx) - case apikey.FieldPurpose: - return m.OldPurpose(ctx) - case apikey.FieldLeaseID: - return m.OldLeaseID(ctx) case apikey.FieldLastUsedAt: return m.OldLastUsedAt(ctx) case apikey.FieldIPWhitelist: @@ -1883,20 +1782,6 @@ func (m *APIKeyMutation) SetField(name string, value ent.Value) error { } m.SetStatus(v) return nil - case apikey.FieldPurpose: - v, ok := value.(string) - if !ok { - return fmt.Errorf("unexpected type %T for field %s", value, name) - } - m.SetPurpose(v) - return nil - case apikey.FieldLeaseID: - v, ok := value.(string) - if !ok { - return fmt.Errorf("unexpected type %T for field %s", value, name) - } - m.SetLeaseID(v) - return nil case apikey.FieldLastUsedAt: v, ok := value.(time.Time) if !ok { @@ -2137,9 +2022,6 @@ func (m *APIKeyMutation) ClearedFields() []string { if m.FieldCleared(apikey.FieldGroupID) { fields = append(fields, apikey.FieldGroupID) } - if m.FieldCleared(apikey.FieldLeaseID) { - fields = append(fields, apikey.FieldLeaseID) - } if m.FieldCleared(apikey.FieldLastUsedAt) { fields = append(fields, apikey.FieldLastUsedAt) } @@ -2181,9 +2063,6 @@ func (m *APIKeyMutation) ClearField(name string) error { case apikey.FieldGroupID: m.ClearGroupID() return nil - case apikey.FieldLeaseID: - m.ClearLeaseID() - return nil case apikey.FieldLastUsedAt: m.ClearLastUsedAt() return nil @@ -2237,12 +2116,6 @@ func (m *APIKeyMutation) ResetField(name string) error { case apikey.FieldStatus: m.ResetStatus() return nil - case apikey.FieldPurpose: - m.ResetPurpose() - return nil - case apikey.FieldLeaseID: - m.ResetLeaseID() - return nil case apikey.FieldLastUsedAt: m.ResetLastUsedAt() return nil diff --git a/backend/ent/runtime/runtime.go b/backend/ent/runtime/runtime.go index 65526b3e64bd..b28ef960eafd 100644 --- a/backend/ent/runtime/runtime.go +++ b/backend/ent/runtime/runtime.go @@ -116,46 +116,36 @@ func init() { apikey.DefaultStatus = apikeyDescStatus.Default.(string) // apikey.StatusValidator is a validator for the "status" field. It is called by the builders before save. apikey.StatusValidator = apikeyDescStatus.Validators[0].(func(string) error) - // apikeyDescPurpose is the schema descriptor for purpose field. - apikeyDescPurpose := apikeyFields[5].Descriptor() - // apikey.DefaultPurpose holds the default value on creation for the purpose field. - apikey.DefaultPurpose = apikeyDescPurpose.Default.(string) - // apikey.PurposeValidator is a validator for the "purpose" field. It is called by the builders before save. - apikey.PurposeValidator = apikeyDescPurpose.Validators[0].(func(string) error) - // apikeyDescLeaseID is the schema descriptor for lease_id field. - apikeyDescLeaseID := apikeyFields[6].Descriptor() - // apikey.LeaseIDValidator is a validator for the "lease_id" field. It is called by the builders before save. - apikey.LeaseIDValidator = apikeyDescLeaseID.Validators[0].(func(string) error) // apikeyDescQuota is the schema descriptor for quota field. - apikeyDescQuota := apikeyFields[10].Descriptor() + apikeyDescQuota := apikeyFields[8].Descriptor() // apikey.DefaultQuota holds the default value on creation for the quota field. apikey.DefaultQuota = apikeyDescQuota.Default.(float64) // apikeyDescQuotaUsed is the schema descriptor for quota_used field. - apikeyDescQuotaUsed := apikeyFields[11].Descriptor() + apikeyDescQuotaUsed := apikeyFields[9].Descriptor() // apikey.DefaultQuotaUsed holds the default value on creation for the quota_used field. apikey.DefaultQuotaUsed = apikeyDescQuotaUsed.Default.(float64) // apikeyDescRateLimit5h is the schema descriptor for rate_limit_5h field. - apikeyDescRateLimit5h := apikeyFields[13].Descriptor() + apikeyDescRateLimit5h := apikeyFields[11].Descriptor() // apikey.DefaultRateLimit5h holds the default value on creation for the rate_limit_5h field. apikey.DefaultRateLimit5h = apikeyDescRateLimit5h.Default.(float64) // apikeyDescRateLimit1d is the schema descriptor for rate_limit_1d field. - apikeyDescRateLimit1d := apikeyFields[14].Descriptor() + apikeyDescRateLimit1d := apikeyFields[12].Descriptor() // apikey.DefaultRateLimit1d holds the default value on creation for the rate_limit_1d field. apikey.DefaultRateLimit1d = apikeyDescRateLimit1d.Default.(float64) // apikeyDescRateLimit7d is the schema descriptor for rate_limit_7d field. - apikeyDescRateLimit7d := apikeyFields[15].Descriptor() + apikeyDescRateLimit7d := apikeyFields[13].Descriptor() // apikey.DefaultRateLimit7d holds the default value on creation for the rate_limit_7d field. apikey.DefaultRateLimit7d = apikeyDescRateLimit7d.Default.(float64) // apikeyDescUsage5h is the schema descriptor for usage_5h field. - apikeyDescUsage5h := apikeyFields[16].Descriptor() + apikeyDescUsage5h := apikeyFields[14].Descriptor() // apikey.DefaultUsage5h holds the default value on creation for the usage_5h field. apikey.DefaultUsage5h = apikeyDescUsage5h.Default.(float64) // apikeyDescUsage1d is the schema descriptor for usage_1d field. - apikeyDescUsage1d := apikeyFields[17].Descriptor() + apikeyDescUsage1d := apikeyFields[15].Descriptor() // apikey.DefaultUsage1d holds the default value on creation for the usage_1d field. apikey.DefaultUsage1d = apikeyDescUsage1d.Default.(float64) // apikeyDescUsage7d is the schema descriptor for usage_7d field. - apikeyDescUsage7d := apikeyFields[18].Descriptor() + apikeyDescUsage7d := apikeyFields[16].Descriptor() // apikey.DefaultUsage7d holds the default value on creation for the usage_7d field. apikey.DefaultUsage7d = apikeyDescUsage7d.Default.(float64) accountMixin := schema.Account{}.Mixin() diff --git a/backend/ent/schema/api_key.go b/backend/ent/schema/api_key.go index a87ca851b48a..5db51270b1bf 100644 --- a/backend/ent/schema/api_key.go +++ b/backend/ent/schema/api_key.go @@ -47,16 +47,6 @@ func (APIKey) Fields() []ent.Field { field.String("status"). MaxLen(20). Default(domain.StatusActive), - field.String("purpose"). - MaxLen(32). - Default("user"). - Comment("Internal lifecycle purpose; user keys remain the public default"), - field.String("lease_id"). - MaxLen(64). - Optional(). - Nillable(). - Unique(). - Comment("Opaque idempotency identifier for short-lived internal leases"), field.Time("last_used_at"). Optional(). Nillable(). @@ -149,8 +139,6 @@ func (APIKey) Indexes() []ent.Index { index.Fields("user_id"), index.Fields("group_id"), index.Fields("status"), - index.Fields("purpose"), - index.Fields("purpose", "expires_at"), index.Fields("deleted_at"), index.Fields("last_used_at"), // Index for quota queries diff --git a/backend/internal/handler/dto/mappers.go b/backend/internal/handler/dto/mappers.go index 2b8b91428761..89f8819ed46c 100644 --- a/backend/internal/handler/dto/mappers.go +++ b/backend/internal/handler/dto/mappers.go @@ -110,10 +110,6 @@ func APIKeyFromService(k *service.APIKey) *APIKey { User: UserFromServiceShallow(k.User), Group: GroupFromServiceShallow(k.Group), } - if k.Purpose != "" && k.Purpose != service.APIKeyPurposeUser { - out.Purpose = k.Purpose - out.LeaseID = k.LeaseID - } if k.Window5hStart != nil && !service.IsWindowExpired(k.Window5hStart, service.RateLimitWindow5h) { t := k.Window5hStart.Add(service.RateLimitWindow5h) out.Reset5hAt = &t diff --git a/backend/internal/handler/dto/types.go b/backend/internal/handler/dto/types.go index 9e913c511877..fc18d690af19 100644 --- a/backend/internal/handler/dto/types.go +++ b/backend/internal/handler/dto/types.go @@ -88,11 +88,6 @@ type APIKey struct { User *User `json:"user,omitempty"` Group *Group `json:"group,omitempty"` - - // Purpose and LeaseID mark internal keys, such as the leased keys of the - // release acceptance runner. Ordinary user keys omit both. - Purpose string `json:"purpose,omitempty"` - LeaseID *string `json:"lease_id,omitempty"` } type Group struct { diff --git a/backend/internal/repository/api_key_repo.go b/backend/internal/repository/api_key_repo.go index 545b7d729b36..9060aa65fd32 100644 --- a/backend/internal/repository/api_key_repo.go +++ b/backend/internal/repository/api_key_repo.go @@ -41,19 +41,6 @@ func (r *apiKeyRepository) activeQuery() *dbent.APIKeyQuery { return r.client.APIKey.Query().Where(apikey.DeletedAtIsNil()) } -func (r *apiKeyRepository) userVisibleQuery() *dbent.APIKeyQuery { - return r.activeQuery().Where(apikey.PurposeEQ(service.APIKeyPurposeUser)) -} - -// listedQuery serves the key lists only administrators read: a user's keys in -// the admin console (ListByUserIDForAdmin), group keys and the usage search. -// It includes internal release-acceptance keys, which carry their purpose in -// the response. The owner's own key list and lookups used by mutations keep -// userVisibleQuery, so those keys never reach the user side and stay read-only. -func (r *apiKeyRepository) listedQuery() *dbent.APIKeyQuery { - return r.activeQuery() -} - func (r *apiKeyRepository) Create(ctx context.Context, key *service.APIKey) error { builder := r.client.APIKey.Create(). SetUserID(key.UserID). @@ -65,13 +52,9 @@ func (r *apiKeyRepository) Create(ctx context.Context, key *service.APIKey) erro SetQuota(key.Quota). SetQuotaUsed(key.QuotaUsed). SetNillableExpiresAt(key.ExpiresAt). - SetNillableLeaseID(key.LeaseID). SetRateLimit5h(key.RateLimit5h). SetRateLimit1d(key.RateLimit1d). SetRateLimit7d(key.RateLimit7d) - if key.Purpose != "" { - builder.SetPurpose(key.Purpose) - } if len(key.IPWhitelist) > 0 { builder.SetIPWhitelist(key.IPWhitelist) @@ -83,8 +66,6 @@ func (r *apiKeyRepository) Create(ctx context.Context, key *service.APIKey) erro created, err := builder.Save(ctx) if err == nil { key.ID = created.ID - key.Purpose = created.Purpose - key.LeaseID = created.LeaseID key.LastUsedAt = created.LastUsedAt key.CreatedAt = created.CreatedAt key.UpdatedAt = created.UpdatedAt @@ -93,7 +74,7 @@ func (r *apiKeyRepository) Create(ctx context.Context, key *service.APIKey) erro } func (r *apiKeyRepository) GetByID(ctx context.Context, id int64) (*service.APIKey, error) { - m, err := r.userVisibleQuery(). + m, err := r.activeQuery(). Where(apikey.IDEQ(id)). WithUser(). WithGroup(). @@ -113,7 +94,7 @@ func (r *apiKeyRepository) GetByID(ctx context.Context, id int64) (*service.APIK // - 不加载完整的 API Key 实体及其关联数据(User、Group 等) // - 适用于删除等只需 key 与用户 ID 的场景 func (r *apiKeyRepository) GetKeyAndOwnerID(ctx context.Context, id int64) (string, int64, error) { - m, err := r.userVisibleQuery(). + m, err := r.activeQuery(). Where(apikey.IDEQ(id)). Select(apikey.FieldKey, apikey.FieldUserID). Only(ctx) @@ -154,8 +135,6 @@ func (r *apiKeyRepository) GetByKeyForAuth(ctx context.Context, key string) (*se apikey.FieldGroupID, apikey.FieldName, apikey.FieldStatus, - apikey.FieldPurpose, - apikey.FieldLeaseID, apikey.FieldIPWhitelist, apikey.FieldIPBlacklist, apikey.FieldQuota, @@ -452,12 +431,8 @@ func (r *apiKeyRepository) deleteWithTombstone(ctx context.Context, exec *dbent. return nil } -func (r *apiKeyRepository) apiKeyListByUserIDQuery(userID int64, filters service.APIKeyListFilters, includeInternal bool) *dbent.APIKeyQuery { - q := r.userVisibleQuery() - if includeInternal { - q = r.listedQuery() - } - q = q.Where(apikey.UserIDEQ(userID)) +func (r *apiKeyRepository) apiKeyListByUserIDQuery(userID int64, filters service.APIKeyListFilters) *dbent.APIKeyQuery { + q := r.activeQuery().Where(apikey.UserIDEQ(userID)) if filters.Search != "" { q = q.Where(apikey.Or( @@ -480,17 +455,7 @@ func (r *apiKeyRepository) apiKeyListByUserIDQuery(userID int64, filters service } func (r *apiKeyRepository) ListByUserID(ctx context.Context, userID int64, params pagination.PaginationParams, filters service.APIKeyListFilters) ([]service.APIKey, *pagination.PaginationResult, error) { - return r.listByUserID(ctx, userID, params, filters, false) -} - -// ListByUserIDForAdmin is the administrator's view of one user's keys: it also -// lists internal release-acceptance keys, marked by their purpose. -func (r *apiKeyRepository) ListByUserIDForAdmin(ctx context.Context, userID int64, params pagination.PaginationParams, filters service.APIKeyListFilters) ([]service.APIKey, *pagination.PaginationResult, error) { - return r.listByUserID(ctx, userID, params, filters, true) -} - -func (r *apiKeyRepository) listByUserID(ctx context.Context, userID int64, params pagination.PaginationParams, filters service.APIKeyListFilters, includeInternal bool) ([]service.APIKey, *pagination.PaginationResult, error) { - q := r.apiKeyListByUserIDQuery(userID, filters, includeInternal) + q := r.apiKeyListByUserIDQuery(userID, filters) total, err := q.Count(ctx) if err != nil { @@ -522,7 +487,7 @@ func (r *apiKeyRepository) listByUserID(ctx context.Context, userID int64, param } func (r *apiKeyRepository) ListAllByUserID(ctx context.Context, userID int64, filters service.APIKeyListFilters) ([]service.APIKey, error) { - keys, err := r.apiKeyListByUserIDQuery(userID, filters, false). + keys, err := r.apiKeyListByUserIDQuery(userID, filters). WithGroup(). Order(dbent.Asc(apikey.FieldID)). All(ctx) @@ -639,7 +604,6 @@ func (r *apiKeyRepository) VerifyOwnership(ctx context.Context, userID int64, ap apikey.UserIDEQ(userID), apikey.IDIn(apiKeyIDs...), apikey.DeletedAtIsNil(), - apikey.PurposeEQ(service.APIKeyPurposeUser), ). IDs(ctx) if err != nil { @@ -649,7 +613,7 @@ func (r *apiKeyRepository) VerifyOwnership(ctx context.Context, userID int64, ap } func (r *apiKeyRepository) CountByUserID(ctx context.Context, userID int64) (int64, error) { - count, err := r.userVisibleQuery().Where(apikey.UserIDEQ(userID)).Count(ctx) + count, err := r.activeQuery().Where(apikey.UserIDEQ(userID)).Count(ctx) return int64(count), err } @@ -659,7 +623,7 @@ func (r *apiKeyRepository) ExistsByKey(ctx context.Context, key string) (bool, e } func (r *apiKeyRepository) ListByGroupID(ctx context.Context, groupID int64, params pagination.PaginationParams) ([]service.APIKey, *pagination.PaginationResult, error) { - q := r.listedQuery().Where(apikey.GroupIDEQ(groupID)) + q := r.activeQuery().Where(apikey.GroupIDEQ(groupID)) total, err := q.Count(ctx) if err != nil { @@ -736,7 +700,7 @@ func apiKeyListOrder(params pagination.PaginationParams) []func(*entsql.Selector // SearchAPIKeys searches API keys by user ID and/or keyword (name) func (r *apiKeyRepository) SearchAPIKeys(ctx context.Context, userID int64, keyword string, limit int) ([]service.APIKey, error) { - q := r.listedQuery() + q := r.activeQuery() if userID > 0 { q = q.Where(apikey.UserIDEQ(userID)) } @@ -763,7 +727,6 @@ func (r *apiKeyRepository) ClearGroupIDByGroupID(ctx context.Context, groupID in Where( apikey.GroupIDEQ(groupID), apikey.DeletedAtIsNil(), - apikey.PurposeEQ(service.APIKeyPurposeUser), ). ClearGroupID(). Save(ctx) @@ -778,7 +741,6 @@ func (r *apiKeyRepository) UpdateGroupIDByUserAndGroup(ctx context.Context, user apikey.UserIDEQ(userID), apikey.GroupIDEQ(oldGroupID), apikey.DeletedAtIsNil(), - apikey.PurposeEQ(service.APIKeyPurposeUser), ). SetGroupID(newGroupID). Save(ctx) @@ -787,12 +749,12 @@ func (r *apiKeyRepository) UpdateGroupIDByUserAndGroup(ctx context.Context, user // CountByGroupID 获取分组的 API Key 数量 func (r *apiKeyRepository) CountByGroupID(ctx context.Context, groupID int64) (int64, error) { - count, err := r.userVisibleQuery().Where(apikey.GroupIDEQ(groupID)).Count(ctx) + count, err := r.activeQuery().Where(apikey.GroupIDEQ(groupID)).Count(ctx) return int64(count), err } func (r *apiKeyRepository) ListKeysByUserID(ctx context.Context, userID int64) ([]string, error) { - keys, err := r.userVisibleQuery(). + keys, err := r.activeQuery(). Where(apikey.UserIDEQ(userID)). Select(apikey.FieldKey). Strings(ctx) @@ -803,7 +765,7 @@ func (r *apiKeyRepository) ListKeysByUserID(ctx context.Context, userID int64) ( } func (r *apiKeyRepository) ListKeysByGroupID(ctx context.Context, groupID int64) ([]string, error) { - keys, err := r.userVisibleQuery(). + keys, err := r.activeQuery(). Where(apikey.GroupIDEQ(groupID)). Select(apikey.FieldKey). Strings(ctx) @@ -937,8 +899,6 @@ func apiKeyEntityToService(m *dbent.APIKey) *service.APIKey { Key: m.Key, Name: m.Name, Status: m.Status, - Purpose: m.Purpose, - LeaseID: m.LeaseID, IPWhitelist: m.IPWhitelist, IPBlacklist: m.IPBlacklist, LastUsedAt: m.LastUsedAt, diff --git a/backend/internal/repository/api_key_repo_integration_test.go b/backend/internal/repository/api_key_repo_integration_test.go index 9b5a505c6457..ada0a201b3c8 100644 --- a/backend/internal/repository/api_key_repo_integration_test.go +++ b/backend/internal/repository/api_key_repo_integration_test.go @@ -86,66 +86,6 @@ func (s *APIKeyRepoSuite) TestGetByKey_NotFound() { s.Require().Error(err, "expected error for non-existent key") } -func (s *APIKeyRepoSuite) TestReleaseAcceptanceKeyIsAdminListedReadOnlyAndAuthenticates() { - user := s.mustCreateUser("release-acceptance-key@test.com") - group := s.mustCreateGroup("g-release-acceptance") - leaseID := "accept-0123456789abcdef0123456789abcdef0123456789abcdef" - key := &service.APIKey{ - UserID: user.ID, - Key: "sk-accept-integration-test", - Name: "Release acceptance (ephemeral)", - GroupID: &group.ID, - Status: service.StatusActive, - Purpose: service.APIKeyPurposeReleaseAcceptance, - LeaseID: &leaseID, - ExpiresAt: ptrTime(time.Now().Add(30 * time.Minute)), - IPWhitelist: []string{"127.0.0.1", "::1"}, - } - s.Require().NoError(s.repo.Create(s.ctx, key)) - s.Require().Equal(service.APIKeyPurposeReleaseAcceptance, key.Purpose) - - _, err := s.repo.GetByID(s.ctx, key.ID) - s.Require().ErrorIs(err, service.ErrAPIKeyNotFound) - - listed, result, err := s.repo.ListByUserID( - s.ctx, - user.ID, - pagination.PaginationParams{Page: 1, PageSize: 20}, - service.APIKeyListFilters{}, - ) - s.Require().NoError(err) - // The owner's own key list never shows the internal key. - s.Require().Empty(listed) - s.Require().Zero(result.Total) - - // Administrators see it with its purpose; it stays read-only because - // lookups used by mutations (GetByID above) do not return it. - adminListed, adminResult, err := s.repo.ListByUserIDForAdmin( - s.ctx, - user.ID, - pagination.PaginationParams{Page: 1, PageSize: 20}, - service.APIKeyListFilters{}, - ) - s.Require().NoError(err) - s.Require().Len(adminListed, 1) - s.Require().EqualValues(1, adminResult.Total) - s.Require().Equal(service.APIKeyPurposeReleaseAcceptance, adminListed[0].Purpose) - s.Require().Equal(leaseID, *adminListed[0].LeaseID) - grouped, groupResult, err := s.repo.ListByGroupID(s.ctx, group.ID, pagination.PaginationParams{Page: 1, PageSize: 20}) - s.Require().NoError(err) - s.Require().Len(grouped, 1) - s.Require().EqualValues(1, groupResult.Total) - searched, err := s.repo.SearchAPIKeys(s.ctx, user.ID, "Release acceptance", 10) - s.Require().NoError(err) - s.Require().Len(searched, 1) - - authenticated, err := s.repo.GetByKeyForAuth(s.ctx, key.Key) - s.Require().NoError(err) - s.Require().Equal(key.ID, authenticated.ID) - s.Require().Equal(service.APIKeyPurposeReleaseAcceptance, authenticated.Purpose) - s.Require().Equal(leaseID, *authenticated.LeaseID) -} - func (s *APIKeyRepoSuite) TestGetByKeyForAuth_PreservesMessagesDispatchModelConfig() { user := s.mustCreateUser("getbykey-auth-dispatch@test.com") group, err := s.client.Group.Create(). diff --git a/backend/internal/service/admin_service_apikey_test.go b/backend/internal/service/admin_service_apikey_test.go index f5348687d7fb..8abd913b94eb 100644 --- a/backend/internal/service/admin_service_apikey_test.go +++ b/backend/internal/service/admin_service_apikey_test.go @@ -565,30 +565,3 @@ func TestAdminService_AdminUpdateAPIKeyGroupID_Unbind_NoAllowedGroupUpdate(t *te require.False(t, userRepo.addGroupCalled) require.False(t, got.AutoGrantedGroupAccess) } - -type adminKeyListRepoStub struct { - APIKeyRepository - userCalls, adminCalls int -} - -func (s *adminKeyListRepoStub) ListByUserID(context.Context, int64, pagination.PaginationParams, APIKeyListFilters) ([]APIKey, *pagination.PaginationResult, error) { - s.userCalls++ - return nil, &pagination.PaginationResult{}, nil -} - -func (s *adminKeyListRepoStub) ListByUserIDForAdmin(context.Context, int64, pagination.PaginationParams, APIKeyListFilters) ([]APIKey, *pagination.PaginationResult, error) { - s.adminCalls++ - return []APIKey{{ID: 5, Purpose: APIKeyPurposeReleaseAcceptance}}, &pagination.PaginationResult{Total: 1}, nil -} - -// The admin console lists a user's internal release-acceptance keys too; the -// user's own key list (ListByUserID) does not. -func TestAdminService_GetUserAPIKeysUsesAdminListing(t *testing.T) { - repo := &adminKeyListRepoStub{} - keys, total, err := (&adminServiceImpl{apiKeyRepo: repo}).GetUserAPIKeys(context.Background(), 9, 1, 20, "created_at", "desc") - require.NoError(t, err) - require.EqualValues(t, 1, total) - require.Equal(t, APIKeyPurposeReleaseAcceptance, keys[0].Purpose) - require.Equal(t, 1, repo.adminCalls) - require.Zero(t, repo.userCalls) -} diff --git a/backend/internal/service/admin_user.go b/backend/internal/service/admin_user.go index 1d12c0f9884c..12f71f96a267 100644 --- a/backend/internal/service/admin_user.go +++ b/backend/internal/service/admin_user.go @@ -601,20 +601,9 @@ func (s *adminServiceImpl) tryAccrueAffiliateRebateForAdminRecharge(ctx context. } } -// apiKeyAdminLister lists one user's keys for administrators, internal -// release-acceptance keys included (marked by their purpose). The user's own -// key list keeps using ListByUserID, which excludes them. -type apiKeyAdminLister interface { - ListByUserIDForAdmin(ctx context.Context, userID int64, params pagination.PaginationParams, filters APIKeyListFilters) ([]APIKey, *pagination.PaginationResult, error) -} - func (s *adminServiceImpl) GetUserAPIKeys(ctx context.Context, userID int64, page, pageSize int, sortBy, sortOrder string) ([]APIKey, int64, error) { params := pagination.PaginationParams{Page: page, PageSize: pageSize, SortBy: sortBy, SortOrder: sortOrder} - list := s.apiKeyRepo.ListByUserID - if lister, ok := s.apiKeyRepo.(apiKeyAdminLister); ok { - list = lister.ListByUserIDForAdmin - } - keys, result, err := list(ctx, userID, params, APIKeyListFilters{}) + keys, result, err := s.apiKeyRepo.ListByUserID(ctx, userID, params, APIKeyListFilters{}) if err != nil { return nil, 0, err } diff --git a/backend/internal/service/api_key.go b/backend/internal/service/api_key.go index 9d499182a55a..b92a8481844b 100644 --- a/backend/internal/service/api_key.go +++ b/backend/internal/service/api_key.go @@ -12,9 +12,6 @@ const ( StatusAPIKeyDisabled = "disabled" StatusAPIKeyQuotaExhausted = "quota_exhausted" StatusAPIKeyExpired = "expired" - - APIKeyPurposeUser = "user" - APIKeyPurposeReleaseAcceptance = "release_acceptance" ) // Rate limit window durations @@ -37,8 +34,6 @@ type APIKey struct { Name string GroupID *int64 Status string - Purpose string - LeaseID *string IPWhitelist []string IPBlacklist []string // 预编译的 IP 规则,用于认证热路径避免重复 ParseIP/ParseCIDR。 diff --git a/backend/internal/service/openai_codex_context_contract.go b/backend/internal/service/openai_codex_context_contract.go deleted file mode 100644 index c23574834435..000000000000 --- a/backend/internal/service/openai_codex_context_contract.go +++ /dev/null @@ -1,135 +0,0 @@ -package service - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" -) - -const ( - // This deterministic self-test reports policy, not production model limits. - OfficialCodexContextContractSuccessLine = "CODEX_CONTEXT_CONTRACT|version=4|valid=true|priority=custom,official,upstream,registry|unknown=unchanged|aggregate=group_minimum|sentinel=preserved" - OfficialCodexContextContractFailureLine = "CODEX_CONTEXT_CONTRACT|valid=false|reason=contract-mismatch" - OfficialCodexContextInvalidArgsLine = "CODEX_CONTEXT_CONTRACT|valid=false|reason=invalid-arguments" - officialCodexContextContractSentinel = "codex-context-contract-v4" -) - -type officialCodexContextContractEnvelope struct { - Models []officialCodexContextContractModel `json:"models"` - ContractSentinel string `json:"contract_sentinel"` -} - -type officialCodexContextContractModel struct { - Slug string `json:"slug"` - ContextWindow *int64 `json:"context_window"` - MaxContextWindow *int64 `json:"max_context_window"` - MaxInputTokens *int64 `json:"max_input_tokens"` - MaxOutputTokens *int64 `json:"max_output_tokens"` - AutoCompactLimit json.RawMessage `json:"auto_compact_token_limit"` - Source string `json:"context_capacity_source"` - Reason string `json:"context_capacity_reason"` - ContractSentinel string `json:"contract_sentinel"` - UnknownCapability json.RawMessage `json:"unknown_capability"` -} - -// VerifyOfficialCodexContextContract exercises the production pure resolver, -// group aggregation and final projection without configuration, network, -// credentials, DB, or Redis. -func VerifyOfficialCodexContextContract() (string, error) { - body, err := buildOfficialCodexContextContractFixture() - if err != nil { - return "", err - } - if err := verifyNormalizedOfficialCodexContextContract(body); err != nil { - return "", err - } - return OfficialCodexContextContractSuccessLine, nil -} - -func buildOfficialCodexContextContractFixture() ([]byte, error) { - custom := modelContextEvidence{ModelContextSourceCustom, ModelContextCapacity{ContextWindow: 512000, MaxContextWindow: 512000}} - upstream := modelContextEvidence{ModelContextSourceUpstream, ModelContextCapacity{ContextWindow: 64000, MaxContextWindow: 128000, MaxInputTokens: 64000, MaxOutputTokens: 8192}} - official := modelContextEvidence{ModelContextSourceOfficial, ModelContextCapacity{ContextWindow: 272000, MaxContextWindow: 872000}} - registry := modelContextEvidence{ModelContextSourceRegistry, ModelContextCapacity{ContextWindow: 400000, MaxOutputTokens: 100000}} - relay := modelContextEvidence{ModelContextSourceUpstream, ModelContextCapacity{ContextWindow: 1050000}} - cases := []struct { - slug string - capacity ResolvedModelContextCapacity - compact int64 - }{ - {"fixture-custom", resolveModelContextEvidence([]modelContextEvidence{custom, upstream, official, registry}), 9999999}, - {"fixture-upstream", resolveModelContextEvidence([]modelContextEvidence{upstream, registry}), 50000}, - {"fixture-official", resolveModelContextEvidence([]modelContextEvidence{upstream, registry, official}), 9999999}, - {"fixture-registry", resolveModelContextEvidence([]modelContextEvidence{registry}), 9999999}, - {"fixture-unknown", resolveModelContextEvidence(nil), 666666}, - {"fixture-group", minimumModelContextCapacity([]ResolvedModelContextCapacity{ - resolveModelContextEvidence([]modelContextEvidence{relay}), - resolveModelContextEvidence([]modelContextEvidence{official}), - }), 9999999}, - } - models := make([]map[string]json.RawMessage, 0, len(cases)) - for _, test := range cases { - fields := map[string]json.RawMessage{ - "slug": json.RawMessage(fmt.Sprintf("%q", test.slug)), - "context_window": json.RawMessage("777000"), - "max_context_window": json.RawMessage("888000"), - "max_input_tokens": json.RawMessage("123000"), - "max_output_tokens": json.RawMessage("456000"), - "auto_compact_token_limit": json.RawMessage(fmt.Sprintf("%d", test.compact)), - "contract_sentinel": json.RawMessage(fmt.Sprintf("%q", officialCodexContextContractSentinel)), - "unknown_capability": json.RawMessage(`{"keep":true}`), - } - ApplyModelContextCapacityToFields(fields, test.capacity, true) - models = append(models, fields) - } - return json.Marshal(map[string]any{"models": models, "contract_sentinel": officialCodexContextContractSentinel}) -} - -func verifyNormalizedOfficialCodexContextContract(body []byte) error { - var envelope officialCodexContextContractEnvelope - if err := json.Unmarshal(body, &envelope); err != nil { - return fmt.Errorf("decode normalized manifest: %w", err) - } - if envelope.ContractSentinel != officialCodexContextContractSentinel { - return errors.New("top-level sentinel changed") - } - checks := []struct { - slug, source, reason, compact string - contextWindow, maxWindow int64 - }{ - {"fixture-custom", "custom", "", "null", 512000, 512000}, - {"fixture-upstream", "upstream", "", "50000", 128000, 128000}, - {"fixture-official", "official", "", "null", 872000, 872000}, - {"fixture-registry", "registry", "", "null", 400000, 400000}, - {"fixture-unknown", "", "", "666666", 777000, 888000}, - {"fixture-group", "official", "group_minimum", "null", 872000, 872000}, - } - if len(envelope.Models) != len(checks) { - return errors.New("model fixture count changed") - } - bySlug := make(map[string]officialCodexContextContractModel, len(envelope.Models)) - for _, model := range envelope.Models { - if _, exists := bySlug[model.Slug]; exists { - return errors.New("duplicate model fixture") - } - bySlug[model.Slug] = model - } - for _, check := range checks { - model, exists := bySlug[check.slug] - if !exists || model.ContextWindow == nil || *model.ContextWindow != check.contextWindow || - model.MaxContextWindow == nil || *model.MaxContextWindow != check.maxWindow || - model.Source != check.source || model.Reason != check.reason || - !bytes.Equal(bytes.TrimSpace(model.AutoCompactLimit), []byte(check.compact)) { - return fmt.Errorf("model %q policy mismatch", check.slug) - } - if (check.source == ModelContextSourceOfficial || check.source == ModelContextSourceCustom) && (model.MaxInputTokens != nil || model.MaxOutputTokens != nil) { - return fmt.Errorf("model %q borrowed independent limits from another source", check.slug) - } - if model.ContractSentinel != officialCodexContextContractSentinel || - !bytes.Equal(bytes.TrimSpace(model.UnknownCapability), []byte(`{"keep":true}`)) { - return errors.New("unrelated model capability changed") - } - } - return nil -} diff --git a/backend/internal/service/openai_codex_context_contract_test.go b/backend/internal/service/openai_codex_context_contract_test.go deleted file mode 100644 index a7195db461de..000000000000 --- a/backend/internal/service/openai_codex_context_contract_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package service - -import ( - "encoding/json" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestModelContextCapacityContractUsesRuntimePolicyAndProjection(t *testing.T) { - line, err := VerifyOfficialCodexContextContract() - require.NoError(t, err) - require.Equal(t, OfficialCodexContextContractSuccessLine, line) - require.Contains(t, line, "version=4") - require.Contains(t, line, "priority=custom,official,upstream,registry") - require.NotContains(t, line, "default_context=") -} - -func TestModelContextCapacityContractFailsClosed(t *testing.T) { - body, err := buildOfficialCodexContextContractFixture() - require.NoError(t, err) - valid := string(body) - tests := []struct{ name, body string }{ - {"invalid envelope", `{"models":`}, - {"wrong custom context", strings.Replace(valid, `"context_window":512000`, `"context_window":512001`, 1)}, - {"wrong priority source", strings.Replace(valid, `"context_capacity_source":"upstream"`, `"context_capacity_source":"official"`, 1)}, - {"maximum forced to default", strings.Replace(valid, `"max_context_window":872000`, `"max_context_window":272000`, 1)}, - {"unsafe compact threshold", strings.Replace(valid, `"auto_compact_token_limit":null`, `"auto_compact_token_limit":9999999`, 1)}, - {"unknown capacity invented", strings.Replace(valid, `"context_window":777000`, `"context_window":200000`, 1)}, - {"group minimum lost", strings.Replace(valid, `"context_capacity_reason":"group_minimum"`, `"context_capacity_reason":"other"`, 1)}, - {"borrowed official output limit", strings.Replace(valid, `"slug":"fixture-official"`, `"slug":"fixture-official","max_output_tokens":8192`, 1)}, - {"sentinel changed", strings.Replace(valid, officialCodexContextContractSentinel, "changed", 1)}, - {"unknown capability changed", strings.Replace(valid, `"keep":true`, `"keep":false`, 1)}, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - require.NotEqual(t, valid, test.body, "mutation must alter the fixture") - require.Error(t, verifyNormalizedOfficialCodexContextContract([]byte(test.body))) - }) - } - var envelope map[string]json.RawMessage - require.NoError(t, json.Unmarshal(body, &envelope)) - var models []json.RawMessage - require.NoError(t, json.Unmarshal(envelope["models"], &models)) - t.Run("missing model", func(t *testing.T) { - envelope["models"], err = json.Marshal(models[1:]) - require.NoError(t, err) - missing, marshalErr := json.Marshal(envelope) - require.NoError(t, marshalErr) - require.Error(t, verifyNormalizedOfficialCodexContextContract(missing)) - }) - t.Run("duplicate model", func(t *testing.T) { - duplicated := append([]json.RawMessage(nil), models...) - duplicated[1] = duplicated[0] - envelope["models"], err = json.Marshal(duplicated) - require.NoError(t, err) - duplicate, marshalErr := json.Marshal(envelope) - require.NoError(t, marshalErr) - require.Error(t, verifyNormalizedOfficialCodexContextContract(duplicate)) - }) -} - -func TestModelContextCapacityContractAcceptsDeterministicFixture(t *testing.T) { - body, err := buildOfficialCodexContextContractFixture() - require.NoError(t, err) - require.NoError(t, verifyNormalizedOfficialCodexContextContract(body)) -} diff --git a/backend/migrations/274_purge_release_acceptance_api_keys.sql b/backend/migrations/274_purge_release_acceptance_api_keys.sql new file mode 100644 index 000000000000..25b4b99c9435 --- /dev/null +++ b/backend/migrations/274_purge_release_acceptance_api_keys.sql @@ -0,0 +1,73 @@ +-- Retire the release-acceptance key leases introduced by 239. +-- +-- Only soft-deleted release_acceptance keys with a nonempty lease are removed. +-- Their usage_logs and billing_usage_entries cascade with the key; the hot +-- and archived billing dedup claims have no foreign key and are removed by +-- the same selected key IDs. Ordinary keys and their data stay. Diagnostic +-- records in ops_error_logs, ops_system_logs and +-- ops_ingress_reject_aggregates keep their original api_key_id and content. +-- +-- Refuse an active acceptance key, an acceptance key without a lease, an +-- unknown purpose or any ordinary key carrying a lease. Nothing is removed +-- when this validation fails. Dropping both columns also removes the old +-- application's ability to authenticate keys: deploy only after the host +-- deployment tool no longer reads them. There is no old-image rollback; +-- repair a failure forward with this schema and the matching application. +-- +-- A repeated run finds neither column and changes nothing. The migration +-- runner owns the transaction; no explicit BEGIN/COMMIT belongs here. +SET LOCAL lock_timeout = '10s'; +SET LOCAL statement_timeout = '120s'; + +LOCK TABLE api_keys IN ACCESS EXCLUSIVE MODE; + +DO $$ +DECLARE + lease_columns integer; + acceptance_key_ids bigint[]; +BEGIN + SELECT count(*) INTO lease_columns + FROM pg_attribute + WHERE attrelid = 'api_keys'::regclass + AND attname IN ('purpose', 'lease_id') + AND NOT attisdropped; + + IF lease_columns = 0 THEN + RETURN; + ELSIF lease_columns <> 2 THEN + RAISE EXCEPTION 'migration 274: release-acceptance lease schema is incomplete; repair it before upgrading'; + END IF; + + IF EXISTS ( + SELECT 1 FROM api_keys + WHERE purpose IS DISTINCT FROM 'user' + AND purpose IS DISTINCT FROM 'release_acceptance' + ) OR EXISTS ( + SELECT 1 FROM api_keys + WHERE purpose = 'user' AND lease_id IS NOT NULL + ) OR EXISTS ( + SELECT 1 FROM api_keys + WHERE purpose = 'release_acceptance' + AND (deleted_at IS NULL OR lease_id IS NULL OR btrim(lease_id) = '') + ) THEN + RAISE EXCEPTION 'migration 274: release-acceptance keys are not retired leased keys, or ordinary keys carry leases; resolve the key state before upgrading'; + END IF; + + SELECT array_agg(id) INTO acceptance_key_ids + FROM api_keys + WHERE purpose = 'release_acceptance'; + + DELETE FROM usage_billing_dedup + WHERE api_key_id = ANY (acceptance_key_ids); + DELETE FROM usage_billing_dedup_archive + WHERE api_key_id = ANY (acceptance_key_ids); + DELETE FROM api_keys + WHERE id = ANY (acceptance_key_ids); + + DROP INDEX IF EXISTS api_keys_acceptance_expiry; + DROP INDEX IF EXISTS api_keys_lease_id_unique; + ALTER TABLE api_keys + DROP CONSTRAINT IF EXISTS api_keys_purpose_valid, + DROP COLUMN purpose, + DROP COLUMN lease_id; +END $$; diff --git a/backend/migrations/release_acceptance_api_key_lease_migration_test.go b/backend/migrations/release_acceptance_api_key_lease_migration_test.go deleted file mode 100644 index fab5508909d7..000000000000 --- a/backend/migrations/release_acceptance_api_key_lease_migration_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package migrations - -import ( - "strings" - "testing" -) - -func TestReleaseAcceptanceAPIKeyLeaseMigrationIsPurposeScoped(t *testing.T) { - raw, err := FS.ReadFile("239_codexrip_release_acceptance_api_key_leases.sql") - if err != nil { - t.Fatalf("read migration: %v", err) - } - sql := string(raw) - for _, required := range []string{ - "purpose VARCHAR(32) NOT NULL DEFAULT 'user'", - "lease_id VARCHAR(64)", - "CHECK (purpose IN ('user', 'release_acceptance'))", - "WHERE lease_id IS NOT NULL", - "WHERE purpose = 'release_acceptance' AND deleted_at IS NULL", - } { - if !strings.Contains(sql, required) { - t.Fatalf("migration missing %q", required) - } - } -} diff --git a/backend/migrations/release_acceptance_retirement_migration_integration_test.go b/backend/migrations/release_acceptance_retirement_migration_integration_test.go new file mode 100644 index 000000000000..3437352ae50c --- /dev/null +++ b/backend/migrations/release_acceptance_retirement_migration_integration_test.go @@ -0,0 +1,138 @@ +//go:build integration + +package migrations_test + +import ( + "context" + "database/sql" + "testing" + "time" + + dbmigrations "github.com/Wei-Shaw/sub2api/migrations" + "github.com/stretchr/testify/require" +) + +func TestMigration274RemovesReleaseAcceptanceKeysSafely(t *testing.T) { + raw, err := dbmigrations.FS.ReadFile("274_purge_release_acceptance_api_keys.sql") + require.NoError(t, err) + for _, state := range []string{"retired", "active_acceptance", "missing_lease", "ordinary_lease"} { + t.Run(state, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + db, _ := remoteSkillMigrationTestDatabase(t) + require.NoError(t, execRemoteSkillSQL(ctx, db, releaseAcceptanceRetirementFixtureSQL)) + apply := func() error { + tx, err := db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer tx.Rollback() + if _, err := tx.ExecContext(ctx, string(raw)); err != nil { + return err + } + return tx.Commit() + } + if state != "retired" { + mutation := map[string]string{ + "active_acceptance": "UPDATE api_keys SET deleted_at = NULL WHERE id = 2", + "missing_lease": "UPDATE api_keys SET lease_id = NULL WHERE id = 2", + "ordinary_lease": "UPDATE api_keys SET lease_id = 'ordinary-lease' WHERE id = 1", + }[state] + _, err := db.ExecContext(ctx, mutation) + require.NoError(t, err) + before := releaseAcceptanceRetirementSnapshot(t, ctx, db) + require.ErrorContains(t, apply(), "release-acceptance keys are not retired leased keys") + require.Equal(t, before, releaseAcceptanceRetirementSnapshot(t, ctx, db), "refusal must roll back every data and schema change") + return + } + + var ordinaryBefore, ordinaryAfter string + ordinaryQuery := `SELECT jsonb_build_object('id', id, 'key', key, 'deleted_at', deleted_at, 'xmin', xmin::text)::text FROM api_keys WHERE id = 1` + require.NoError(t, db.QueryRowContext(ctx, ordinaryQuery).Scan(&ordinaryBefore)) + ordinaryRows := map[string]string{} + for _, table := range []string{"usage_logs", "billing_usage_entries", "usage_billing_dedup", "usage_billing_dedup_archive"} { + var row string + require.NoError(t, db.QueryRowContext(ctx, "SELECT to_jsonb(t)::text FROM "+table+" t WHERE api_key_id = 1").Scan(&row)) + ordinaryRows[table] = row + } + diagnostics := map[string]string{} + for _, table := range []string{"ops_error_logs", "ops_system_logs", "ops_ingress_reject_aggregates"} { + diagnostics[table] = releaseAcceptanceRetirementTable(t, ctx, db, table) + } + require.NoError(t, apply()) + require.NoError(t, db.QueryRowContext(ctx, ordinaryQuery).Scan(&ordinaryAfter)) + require.Equal(t, ordinaryBefore, ordinaryAfter, "ordinary key values and xmin must stay") + for _, table := range []string{"api_keys", "usage_logs", "billing_usage_entries", "usage_billing_dedup", "usage_billing_dedup_archive"} { + var count int + require.NoError(t, db.QueryRowContext(ctx, "SELECT count(*) FROM "+table).Scan(&count)) + require.Equal(t, 1, count, "only the ordinary key's row remains in %s", table) + } + for table, before := range ordinaryRows { + var row string + require.NoError(t, db.QueryRowContext(ctx, "SELECT to_jsonb(t)::text FROM "+table+" t WHERE api_key_id = 1").Scan(&row)) + require.Equal(t, before, row, "ordinary key usage and claims in %s stay", table) + } + for table, before := range diagnostics { + require.Equal(t, before, releaseAcceptanceRetirementTable(t, ctx, db, table), "diagnostic key references and content in %s stay", table) + } + var nullAuditReferences int + require.NoError(t, db.QueryRowContext(ctx, "SELECT count(*) FROM prompt_audit_events WHERE api_key_id IS NULL").Scan(&nullAuditReferences)) + require.Equal(t, 2, nullAuditReferences, "SET NULL audit references must retain their rows") + var leaseObjects int + require.NoError(t, db.QueryRowContext(ctx, `SELECT + (SELECT count(*) FROM pg_attribute WHERE attrelid = 'api_keys'::regclass AND attname IN ('purpose', 'lease_id') AND NOT attisdropped) + + (SELECT count(*) FROM pg_constraint WHERE conrelid = 'api_keys'::regclass AND conname = 'api_keys_purpose_valid') + + (SELECT count(*) FROM pg_class WHERE relnamespace = (SELECT relnamespace FROM pg_class WHERE oid = 'api_keys'::regclass) AND relname IN ('api_keys_acceptance_expiry', 'api_keys_lease_id_unique'))`).Scan(&leaseObjects)) + require.Zero(t, leaseObjects, "both lease columns, dedicated indexes and constraint are gone") + after := releaseAcceptanceRetirementSnapshot(t, ctx, db) + require.NoError(t, apply()) + require.Equal(t, after, releaseAcceptanceRetirementSnapshot(t, ctx, db), "reapplying after the columns are gone is safe") + }) + } +} + +func releaseAcceptanceRetirementTable(t *testing.T, ctx context.Context, db *sql.DB, table string) string { + t.Helper() + var rows string + require.NoError(t, db.QueryRowContext(ctx, "SELECT COALESCE(jsonb_agg(to_jsonb(t) ORDER BY to_jsonb(t)::text), '[]'::jsonb)::text FROM "+table+" t").Scan(&rows)) + return rows +} + +func releaseAcceptanceRetirementSnapshot(t *testing.T, ctx context.Context, db *sql.DB) map[string]string { + t.Helper() + rows := map[string]string{} + for _, table := range []string{"api_keys", "usage_logs", "billing_usage_entries", "usage_billing_dedup", "usage_billing_dedup_archive", "ops_error_logs", "ops_system_logs", "ops_ingress_reject_aggregates", "prompt_audit_events"} { + rows[table] = releaseAcceptanceRetirementTable(t, ctx, db, table) + } + return rows +} + +const releaseAcceptanceRetirementFixtureSQL = ` +CREATE TABLE api_keys ( + id BIGINT PRIMARY KEY, key TEXT NOT NULL, purpose VARCHAR(32) NOT NULL DEFAULT 'user', + lease_id VARCHAR(64), expires_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, + CONSTRAINT api_keys_purpose_valid CHECK (purpose IN ('user', 'release_acceptance')) +); +CREATE UNIQUE INDEX api_keys_lease_id_unique ON api_keys (lease_id) WHERE lease_id IS NOT NULL; +CREATE INDEX api_keys_acceptance_expiry ON api_keys (expires_at) WHERE purpose = 'release_acceptance' AND deleted_at IS NULL; +CREATE TABLE usage_logs (id BIGINT PRIMARY KEY, api_key_id BIGINT NOT NULL REFERENCES api_keys(id) ON DELETE CASCADE, amount NUMERIC NOT NULL); +CREATE TABLE billing_usage_entries (id BIGINT PRIMARY KEY, api_key_id BIGINT NOT NULL REFERENCES api_keys(id) ON DELETE CASCADE, amount NUMERIC NOT NULL); +CREATE TABLE usage_billing_dedup (request_id TEXT NOT NULL, api_key_id BIGINT NOT NULL, PRIMARY KEY (request_id, api_key_id)); +CREATE TABLE usage_billing_dedup_archive (request_id TEXT NOT NULL, api_key_id BIGINT NOT NULL, PRIMARY KEY (request_id, api_key_id)); +CREATE TABLE ops_error_logs (id BIGINT PRIMARY KEY, api_key_id BIGINT NOT NULL, body TEXT NOT NULL); +CREATE TABLE ops_system_logs (id BIGINT PRIMARY KEY, api_key_id BIGINT NOT NULL, body TEXT NOT NULL); +CREATE TABLE ops_ingress_reject_aggregates (id BIGINT PRIMARY KEY, api_key_id BIGINT NOT NULL, body TEXT NOT NULL); +CREATE TABLE prompt_audit_events (id BIGINT PRIMARY KEY, api_key_id BIGINT REFERENCES api_keys(id) ON DELETE SET NULL, body TEXT NOT NULL); +INSERT INTO api_keys VALUES + (1, 'ordinary-key', 'user', NULL, NULL, NULL), + (2, 'retired-key-2', 'release_acceptance', 'acceptance-2', '2026-09-01', '2026-09-01'), + (3, 'retired-key-3', 'release_acceptance', 'acceptance-3', '2026-09-07', '2026-09-07'); +INSERT INTO usage_logs VALUES (1, 1, 0.5), (2, 2, 0.25), (3, 3, 0.75); +INSERT INTO billing_usage_entries SELECT * FROM usage_logs; +INSERT INTO usage_billing_dedup VALUES ('ordinary-request', 1), ('acceptance-request-2', 2), ('acceptance-request-3', 3); +INSERT INTO usage_billing_dedup_archive SELECT * FROM usage_billing_dedup; +INSERT INTO ops_error_logs VALUES (1, 1, 'ordinary-error'), (2, 2, 'acceptance-error'), (3, 3, 'acceptance-error-3'); +INSERT INTO ops_system_logs SELECT * FROM ops_error_logs; +INSERT INTO ops_ingress_reject_aggregates SELECT * FROM ops_error_logs; +INSERT INTO prompt_audit_events SELECT * FROM ops_error_logs; +` diff --git a/frontend/src/components/admin/user/UserApiKeysModal.vue b/frontend/src/components/admin/user/UserApiKeysModal.vue index be1d321e47c6..e7c2bf2bc728 100644 --- a/frontend/src/components/admin/user/UserApiKeysModal.vue +++ b/frontend/src/components/admin/user/UserApiKeysModal.vue @@ -13,8 +13,7 @@
-
{{ key.name }}{{ key.status }}{{ t('admin.users.apiKeyPurposeReadOnly', { purpose: key.purpose }) }}
-

{{ t('admin.users.apiKeyLease', { lease: key.lease_id }) }}

+
{{ key.name }}{{ key.status }}

{{ key.key.substring(0, 20) }}...{{ key.key.substring(key.key.length - 8) }}

@@ -25,7 +24,7 @@ :ref="(el) => setGroupButtonRef(key.id, el)" @click="openGroupSelector(key)" class="-mx-1 -my-0.5 flex cursor-pointer items-center gap-1 rounded-md px-1 py-0.5 transition-colors hover:bg-gray-100 disabled:cursor-default disabled:hover:bg-transparent dark:hover:bg-dark-700" - :disabled="updatingKeyIds.has(key.id) || isInternalKey(key)" + :disabled="updatingKeyIds.has(key.id)" > !!key.purpose && key.purpose !== 'user' -const apiKeys = ref([]) +const apiKeys = ref([]) const allGroups = ref([]) const loading = ref(false) let requestVersion = 0 @@ -188,8 +183,7 @@ const loadGroups = async () => { const DROPDOWN_HEIGHT = 272 // max-h-64 = 16rem = 256px + padding const DROPDOWN_GAP = 4 -const openGroupSelector = (key: AdminApiKey) => { - if (isInternalKey(key)) return +const openGroupSelector = (key: ApiKey) => { if (groupSelectorKeyId.value === key.id) { closeGroupSelector() } else { diff --git a/frontend/src/i18n/locales/en/admin/overview.ts b/frontend/src/i18n/locales/en/admin/overview.ts index ec4028653cb4..e6e07ddd6532 100644 --- a/frontend/src/i18n/locales/en/admin/overview.ts +++ b/frontend/src/i18n/locales/en/admin/overview.ts @@ -629,8 +629,6 @@ export default { apiKeys: 'API Keys', userApiKeys: 'User API Keys', noApiKeys: 'This user has no API keys', - apiKeyPurposeReadOnly: 'Internal purpose: {purpose} (read-only)', - apiKeyLease: 'Lease: {lease}', group: 'Group', none: 'None', groupChangedSuccess: 'Group updated successfully', diff --git a/frontend/src/i18n/locales/zh/admin/overview.ts b/frontend/src/i18n/locales/zh/admin/overview.ts index deec2a439f75..85426f04b63a 100644 --- a/frontend/src/i18n/locales/zh/admin/overview.ts +++ b/frontend/src/i18n/locales/zh/admin/overview.ts @@ -607,8 +607,6 @@ export default { apiKeys: 'API密钥', userApiKeys: '用户 API 密钥', noApiKeys: '此用户暂无 API 密钥', - apiKeyPurposeReadOnly: '内部用途:{purpose}(只读)', - apiKeyLease: '租约:{lease}', group: '分组', none: '无', groupChangedSuccess: '分组修改成功', From 7d51affb4b9a76d049c74880daec28827304a6e4 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 15:43:46 +0800 Subject: [PATCH 02/21] ci: simplify production deployment to a single image operation --- .downstream/README.md | 4 +- .downstream/native-domains.md | 8 +- .../test_upstream_automation_contract.py | 17 +- .github/scripts/upstream_promote.py | 7 +- .github/workflows/downstream-release.yml | 3 - .github/workflows/production-deploy.yml | 240 +------ .github/workflows/upstream-auto-deploy.yml | 7 +- DOWNSTREAM.md | 5 +- deploy/README.md | 112 +--- .../tests/production-deploy-workflow-test.sh | 619 ++++-------------- .../api/__tests__/downstreamStatus.spec.ts | 2 +- 11 files changed, 192 insertions(+), 832 deletions(-) diff --git a/.downstream/README.md b/.downstream/README.md index 785bea524681..836ac2190675 100644 --- a/.downstream/README.md +++ b/.downstream/README.md @@ -14,8 +14,8 @@ create a named issue with the conflicted paths. After a safe candidate merges, automation creates the immutable `vX.Y.Z-codexrip.1` tag once. The normal Downstream Release workflow builds and attests the linux/amd64 OCI image. A successful release dispatches Production -Deploy with `runtime=preserve`; that run waits at the GitHub `production` -Environment for the configured approval. Authorized delegated maintenance may +Deploy with `release_tag` and `confirmation=DEPLOY`; that run waits at the GitHub +`production` Environment for the configured approval. Authorized delegated maintenance may complete that approval; the release workflow does not approve itself. Sub2API does not store a GitHub token. The admin VersionBadge reads only public diff --git a/.downstream/native-domains.md b/.downstream/native-domains.md index c46c558b8424..60dd5807e1da 100644 --- a/.downstream/native-domains.md +++ b/.downstream/native-domains.md @@ -75,12 +75,12 @@ they never silently enable features. ## Release and rollback boundary The host is delivered as one immutable OCI image with image provenance. Normal -deployment uses the existing fixed-image `deploy-preserve` flow. It does not add +deployment uses the fixed-image `deploy` flow. It does not add backups, canaries, model calls or automatic rollback. -`rollback-preserve` still requires a verified compatible data contract. The -deployer recognizes the old and native prompt/skill directory locations by the -same content hashes; missing or ambiguous trees and changed schema remain errors. +An older tag uses the same deployment form and requires database migrations +compatible with that image. Deployment does not restore dropped schema or data; +the migration boundaries below determine whether an earlier image can start. Migration 264 has no down path. Images at or before v0.2.11-codexrip.5 need `sub2api_plugin_state` and `sub2api_plugin_leases`, which it drops, for their diff --git a/.github/scripts/test_upstream_automation_contract.py b/.github/scripts/test_upstream_automation_contract.py index 03e70555a316..fb01cbca9590 100644 --- a/.github/scripts/test_upstream_automation_contract.py +++ b/.github/scripts/test_upstream_automation_contract.py @@ -50,13 +50,18 @@ def test_safe_merge_tags_once_and_handoff_waits_for_approval(self): self.assertIn("-codexrip.1", self.promoter) self.assertIn("endsWith(github.event.workflow_run.head_branch, '-codexrip.1')", self.handoff) self.assertIn("Manual codexrip releases must remain independent", self.handoff) - self.assertIn("operation=deploy-preserve", self.handoff) + self.assertIn('title="Deploy ${RELEASE_TAG}"', self.handoff) + self.assertIn('-f release_tag="$RELEASE_TAG"', self.handoff) + self.assertIn('-f confirmation=DEPLOY', self.handoff) + self.assertNotIn('operation=', self.handoff) self.assertIn("environment:\n name: production", self.production) - self.assertIn("runtime=preserve", self.production) + self.assertIn('run-name: Deploy ${{ inputs.release_tag }}', self.production) + self.assertIn('remote_command="deploy ${IMAGE_REF}"', self.production) + self.assertNotIn('runtime=', self.production) self.assertNotIn("pending_deployments", self.handoff) self.assertNotIn("pending_deployments", self.promoter) self.assertIn("--match-head-commit", self.promoter) - self.assertIn("operation=deploy-preserve", self.promoter) + self.assertNotIn('operation=', self.promoter) self.assertIn("source_sha", self.publisher) self.assertIn("ref: refs/tags/${{ env.RELEASE_TAG }}", self.publisher) self.assertIn("ref: ${{ needs.verify.outputs.source_sha }}", self.publisher) @@ -246,14 +251,14 @@ def run_command(*args): return merged return "" - for existing in (False, True): + for existing in (None, f"Deploy {self.tag}", f"Deploy {self.tag} (preserve)"): def read_api(path, *args): if path == "pulls/152": return pr if path == "git/refs": return {} if path == "actions/workflows/production-deploy.yml/runs?per_page=100": - runs = [{"display_title": f"Deploy {self.tag} (preserve)", "status": "in_progress", + runs = [{"display_title": existing, "status": "in_progress", "conclusion": None, "html_url": "https://github.com/example/run/18"}] if existing else [] return {"workflow_runs": runs} self.fail(f"unexpected API call: {path}") @@ -274,7 +279,7 @@ def read_api(path, *args): dispatches = [c for c in command.call_args_list if c.args[:3] == ("gh", "workflow", "run")] self.assertEqual(dispatches, [] if existing else [call("gh", "workflow", "run", "production-deploy.yml", "--repo", "HTExplicit/sub2api", "--ref", "main", "-f", - "operation=deploy-preserve", "-f", f"release_tag={self.tag}", "-f", "confirmation=DEPLOY")]) + f"release_tag={self.tag}", "-f", "confirmation=DEPLOY")]) if __name__ == "__main__": diff --git a/.github/scripts/upstream_promote.py b/.github/scripts/upstream_promote.py index 7830216dc65e..ef40a4491737 100644 --- a/.github/scripts/upstream_promote.py +++ b/.github/scripts/upstream_promote.py @@ -183,16 +183,17 @@ def promote(number: int) -> None: else: api("git/refs", "-X", "POST", "-f", f"ref=refs/tags/{tag}", "-f", f"sha={merged}") ensure_release(tag, merged) - title = f"Deploy {tag} (preserve)" + # Reuse deployments already dispatched before the form changed. + titles = {f"Deploy {tag}", f"Deploy {tag} (preserve)"} deployments = api("actions/workflows/production-deploy.yml/runs?per_page=100")["workflow_runs"] - previous = [r for r in deployments if r.get("display_title") == title] + previous = [r for r in deployments if r.get("display_title") in titles] if previous: if previous[0]["status"] == "completed" and previous[0]["conclusion"] != "success": raise RuntimeError("previous production run failed; runtime audit required before retry") print("Existing protected deployment: " + previous[0]["html_url"]) return command("gh", "workflow", "run", "production-deploy.yml", "--repo", REPOSITORY, - "--ref", "main", "-f", "operation=deploy-preserve", "-f", f"release_tag={tag}", "-f", "confirmation=DEPLOY") + "--ref", "main", "-f", f"release_tag={tag}", "-f", "confirmation=DEPLOY") print(f"Protected deployment dispatched: {tag}; production approval remains required.") diff --git a/.github/workflows/downstream-release.yml b/.github/workflows/downstream-release.yml index 6b24c551edad..96c863ee54fd 100644 --- a/.github/workflows/downstream-release.yml +++ b/.github/workflows/downstream-release.yml @@ -122,9 +122,6 @@ jobs: org.opencontainers.image.revision=${{ needs.verify.outputs.source_sha }} org.opencontainers.image.created=${{ env.BUILD_DATE }} org.opencontainers.image.licenses=LGPL-3.0 - io.github.htexplicit.upstream-version=${{ env.UPSTREAM_VERSION }} - io.github.htexplicit.patch=codexrip - io.github.htexplicit.cindy-platform-v1=true build-args: | VERSION=${{ env.VERSION }} COMMIT=${{ needs.verify.outputs.source_sha }} diff --git a/.github/workflows/production-deploy.yml b/.github/workflows/production-deploy.yml index 82f632bdd566..cba41b2242cb 100644 --- a/.github/workflows/production-deploy.yml +++ b/.github/workflows/production-deploy.yml @@ -1,73 +1,17 @@ name: Production Deploy -run-name: >- - ${{ inputs.operation == 'rollback' && format('Rollback to {0}', inputs.release_tag) || inputs.operation == 'rollback-preserve' && format('Rollback to {0} (preserve)', inputs.release_tag) || inputs.operation == 'reconcile-runtime' && format('Reconcile runtime for {0}', inputs.release_tag) || inputs.operation == 'deploy-preserve' && format('Deploy {0} (preserve)', inputs.release_tag) || format('Deploy {0} (explicit)', inputs.release_tag) }} +run-name: Deploy ${{ inputs.release_tag }} on: workflow_dispatch: inputs: - operation: - description: 'Deploy, reconcile an exact current release, or roll back' - required: true - default: deploy - type: choice - options: - - deploy - - deploy-preserve - - reconcile-runtime - - rollback - - rollback-preserve release_tag: - description: 'Target release tag; for reconcile, the exact release currently running' + description: 'Target immutable release tag; older releases require compatible database migrations' required: true type: string - expected_current_release_tag: - description: 'Rollback only: exact release tag currently running in production' - required: false - default: '' - type: string confirmation: - description: 'Type DEPLOY, RECONCILE, or ROLLBACK for the selected operation' + description: 'Type DEPLOY to apply the release' required: true type: string - cindy_health: - description: 'Enable Cindy health tracking and exact budget confirmation' - required: true - default: false - type: boolean - cindy_capability_catalog: - description: 'Enable the verified Cindy model and protocol catalog' - required: true - default: false - type: boolean - cindy_search: - description: 'Enable Cindy Search and its supported protocol fallback' - required: true - default: false - type: boolean - image_studio: - description: 'Enable verified Image Studio capabilities (Cindy-only in this release)' - required: true - default: false - type: boolean - cindy_responses_image_bridge: - description: 'Enable the GPT Image 2 Responses image bridge' - required: true - default: false - type: boolean - interrupt_business: - description: 'Temporarily stop Sub2API after backup to drain active requests before recreation' - required: true - default: false - type: boolean - resource_profile: - description: 'Sub2API memory profile for this deployment' - required: true - default: preserve - type: choice - options: - - preserve - - auto - - high permissions: contents: read @@ -82,13 +26,6 @@ jobs: runs-on: ubuntu-latest outputs: image_ref: ${{ steps.resolve.outputs.image_ref }} - expected_current_image_ref: ${{ steps.resolve.outputs.expected_current_image_ref }} - release_tag: ${{ steps.resolve.outputs.release_tag }} - operation: ${{ steps.resolve.outputs.operation }} - cindy_rollout: ${{ steps.resolve.outputs.cindy_rollout }} - maintenance_spec: ${{ steps.resolve.outputs.maintenance_spec }} - runtime_spec: ${{ steps.resolve.outputs.runtime_spec }} - resource_spec: ${{ steps.resolve.outputs.resource_spec }} steps: - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: @@ -103,30 +40,11 @@ jobs: id: resolve env: GH_TOKEN: ${{ github.token }} - OPERATION: ${{ inputs.operation }} RELEASE_TAG: ${{ inputs.release_tag }} - EXPECTED_CURRENT_RELEASE_TAG: ${{ inputs.expected_current_release_tag }} CONFIRMATION: ${{ inputs.confirmation }} - CINDY_HEALTH: ${{ inputs.cindy_health }} - CINDY_CAPABILITY_CATALOG: ${{ inputs.cindy_capability_catalog }} - CINDY_SEARCH: ${{ inputs.cindy_search }} - IMAGE_STUDIO: ${{ inputs.image_studio }} - CINDY_RESPONSES_IMAGE_BRIDGE: ${{ inputs.cindy_responses_image_bridge }} - INTERRUPT_BUSINESS: ${{ inputs.interrupt_business }} - RESOURCE_PROFILE: ${{ inputs.resource_profile }} shell: bash run: | set -euo pipefail - runtime_mode=explicit - if [[ "$OPERATION" == deploy-preserve ]]; then - OPERATION=deploy - runtime_mode=preserve - elif [[ "$OPERATION" == rollback-preserve ]]; then - # Keeps the running runtime flags; the host refuses unless the data contract is unchanged. - OPERATION=rollback - runtime_mode=preserve - fi - RESOURCE_PROFILE="${RESOURCE_PROFILE:-preserve}" log() { printf 'RESOLVE|%s\n' "$1" >&2; } validate_release_tag() { @@ -134,7 +52,7 @@ jobs: } resolve_release_image() { - local tag=$1 image_role=$2 tag_commit version image inspect digest image_revision image_platform_v1 release_state release_assets release_body + local tag=$1 tag_commit version image digest image_revision release_state release_body local release_image_ref='' release_source='' release_image_count=0 release_source_count=0 line local image_line_re='^Image: `([^`]+)`$' local source_line_re='^Source: `([0-9a-f]{40})`$' @@ -142,11 +60,6 @@ jobs: release_state=$(gh release view "$tag" --json tagName,isDraft,isPrerelease \ --jq '[.tagName,.isDraft,.isPrerelease] | @tsv') || return 1 [[ "$release_state" == "${tag}"$'\tfalse\tfalse' ]] || return 1 - release_assets=$(gh release view "$tag" --json assets --jq '.assets[].name') || return 1 - if grep -Eq '^(seed-descriptor\.json|bundle-manifest\.json|codexrip-reverse-skill-.*\.zip(\.sha256)?|bootstrap-reverse-skill\.(ps1|py))$' <<<"$release_assets"; then - echo "Release $tag contains a removed Skill-specific asset" >&2 - return 1 - fi log "fetch-tag" git fetch origin "refs/tags/${tag}:refs/tags/${tag}" main || return 1 log "rev-list" @@ -176,96 +89,13 @@ jobs: image_revision=$(docker buildx imagetools inspect "${image}@${digest}" --format '{{ index .Image.Config.Labels "org.opencontainers.image.revision" }}') || { log "revision-inspect-failed"; return 1; } log "revision=$image_revision" [[ "$image_revision" == "$tag_commit" ]] || { log "revision-mismatch"; return 1; } - image_platform_v1=$(docker buildx imagetools inspect "${image}@${digest}" --format '{{ index .Image.Config.Labels "io.github.htexplicit.cindy-platform-v1" }}') || { log "platform-inspect-failed"; return 1; } - log "platform=$image_platform_v1" - case "$image_role" in - platform) - [[ "$image_platform_v1" == true ]] || return 1 - ;; - rollback-target) - [[ "$image_platform_v1" == true || "$image_platform_v1" == false || -z "$image_platform_v1" || "$image_platform_v1" == '' ]] || return 1 - ;; - *) - return 1 - ;; - esac printf '%s@%s\n' "$image" "$digest" } - version_strictly_less() { - local target=$1 current=$2 first - [[ "$target" != "$current" ]] || return 1 - first=$(printf '%s\n%s\n' "$target" "$current" | LC_ALL=C sort -V | head -n 1) - [[ "$first" == "$target" ]] - } - validate_release_tag "$RELEASE_TAG" || exit 1 - case "$OPERATION" in - deploy) - [[ "$CONFIRMATION" == DEPLOY ]] || exit 1 - [[ -z "$EXPECTED_CURRENT_RELEASE_TAG" ]] || exit 1 - ;; - reconcile-runtime) - [[ "$CONFIRMATION" == RECONCILE ]] || exit 1 - [[ -z "$EXPECTED_CURRENT_RELEASE_TAG" ]] || exit 1 - ;; - rollback) - [[ "$CONFIRMATION" == ROLLBACK ]] || exit 1 - validate_release_tag "$EXPECTED_CURRENT_RELEASE_TAG" || exit 1 - version_strictly_less "$RELEASE_TAG" "$EXPECTED_CURRENT_RELEASE_TAG" || exit 1 - ;; - *) - echo 'Operation must be deploy, reconcile-runtime, or rollback' >&2 - exit 1 - ;; - esac - [[ "$runtime_mode" == explicit || "$runtime_mode" == preserve ]] || exit 1 - [[ "$INTERRUPT_BUSINESS" == true || "$INTERRUPT_BUSINESS" == false ]] || exit 1 - [[ "$RESOURCE_PROFILE" == preserve || "$RESOURCE_PROFILE" == auto || "$RESOURCE_PROFILE" == high ]] || exit 1 - if [[ "$runtime_mode" == preserve ]]; then - [[ "$INTERRUPT_BUSINESS" == false ]] || exit 1 - [[ "$OPERATION" == deploy || "$OPERATION" == rollback ]] || exit 1 - [[ "$RESOURCE_PROFILE" == preserve ]] || exit 1 - else - for flag in "$CINDY_HEALTH" "$CINDY_CAPABILITY_CATALOG" "$CINDY_SEARCH" "$IMAGE_STUDIO" "$CINDY_RESPONSES_IMAGE_BRIDGE"; do - [[ "$flag" == true || "$flag" == false ]] || exit 1 - done - if [[ "$OPERATION" == rollback ]]; then - [[ "$INTERRUPT_BUSINESS" == false ]] || exit 1 - fi - fi - - expected_current_image_ref='' - case "$OPERATION" in - deploy|reconcile-runtime) - image_ref=$(resolve_release_image "$RELEASE_TAG" platform) || exit 1 - ;; - rollback) - image_ref=$(resolve_release_image "$RELEASE_TAG" rollback-target) || exit 1 - expected_current_image_ref=$(resolve_release_image "$EXPECTED_CURRENT_RELEASE_TAG" platform) || exit 1 - [[ "$expected_current_image_ref" != "$image_ref" ]] || exit 1 - ;; - esac - + [[ "$CONFIRMATION" == DEPLOY ]] || exit 1 + image_ref=$(resolve_release_image "$RELEASE_TAG") || exit 1 echo "image_ref=${image_ref}" >> "$GITHUB_OUTPUT" - echo "expected_current_image_ref=${expected_current_image_ref}" >> "$GITHUB_OUTPUT" - echo "release_tag=${RELEASE_TAG}" >> "$GITHUB_OUTPUT" - echo "operation=${OPERATION}" >> "$GITHUB_OUTPUT" - if [[ "$runtime_mode" == preserve ]]; then - echo 'runtime_spec=runtime=preserve' >> "$GITHUB_OUTPUT" - echo 'cindy_rollout=' >> "$GITHUB_OUTPUT" - echo 'maintenance_spec=' >> "$GITHUB_OUTPUT" - echo 'resource_spec=resource=preserve' >> "$GITHUB_OUTPUT" - else - echo 'runtime_spec=runtime=explicit' >> "$GITHUB_OUTPUT" - echo "cindy_rollout=cindy=${CINDY_HEALTH},${CINDY_CAPABILITY_CATALOG},${CINDY_SEARCH},${IMAGE_STUDIO},${CINDY_RESPONSES_IMAGE_BRIDGE}" >> "$GITHUB_OUTPUT" - if [[ ("$OPERATION" == deploy || "$OPERATION" == reconcile-runtime) && "$INTERRUPT_BUSINESS" == true ]]; then - echo 'maintenance_spec=maintenance=interrupt' >> "$GITHUB_OUTPUT" - else - echo 'maintenance_spec=' >> "$GITHUB_OUTPUT" - fi - echo "resource_spec=resource=${RESOURCE_PROFILE}" >> "$GITHUB_OUTPUT" - fi deploy: needs: resolve @@ -285,72 +115,18 @@ jobs: printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts chmod 600 ~/.ssh/sub2api_deploy ~/.ssh/known_hosts ssh-keygen -y -f ~/.ssh/sub2api_deploy >/dev/null - - name: Apply immutable release operation + - name: Apply immutable release image env: VPS_HOST: ${{ secrets.VPS_HOST }} VPS_PORT: ${{ secrets.VPS_PORT }} VPS_USER: ${{ secrets.VPS_USER }} - OPERATION: ${{ needs.resolve.outputs.operation }} IMAGE_REF: ${{ needs.resolve.outputs.image_ref }} - EXPECTED_CURRENT_IMAGE_REF: ${{ needs.resolve.outputs.expected_current_image_ref }} - CINDY_ROLLOUT: ${{ needs.resolve.outputs.cindy_rollout }} - MAINTENANCE_SPEC: ${{ needs.resolve.outputs.maintenance_spec }} - RUNTIME_SPEC: ${{ needs.resolve.outputs.runtime_spec }} - RESOURCE_SPEC: ${{ needs.resolve.outputs.resource_spec }} shell: bash run: | set -euo pipefail - RESOURCE_SPEC="${RESOURCE_SPEC:-resource=preserve}" [[ "$VPS_PORT" =~ ^[0-9]+$ ]] || exit 1 [[ "$IMAGE_REF" =~ ^ghcr\.io/htexplicit/sub2api:[0-9]+\.[0-9]+\.[0-9]+-codexrip\.[1-9][0-9]*@sha256:[0-9a-f]{64}$ ]] || exit 1 - [[ "$RUNTIME_SPEC" == runtime=explicit || "$RUNTIME_SPEC" == runtime=preserve ]] || exit 1 - [[ "$RESOURCE_SPEC" =~ ^resource=(preserve|auto|high)$ ]] || exit 1 - if [[ "$RUNTIME_SPEC" == runtime=explicit ]]; then - [[ "$CINDY_ROLLOUT" =~ ^cindy=(true|false),(true|false),(true|false),(true|false),(true|false)$ ]] || exit 1 - [[ -z "$MAINTENANCE_SPEC" || "$MAINTENANCE_SPEC" == maintenance=interrupt ]] || exit 1 - [[ "$OPERATION" == deploy || "$OPERATION" == reconcile-runtime || -z "$MAINTENANCE_SPEC" ]] || exit 1 - else - [[ -z "$CINDY_ROLLOUT" && -z "$MAINTENANCE_SPEC" && "$RESOURCE_SPEC" == resource=preserve ]] || exit 1 - [[ "$OPERATION" == deploy || "$OPERATION" == rollback ]] || exit 1 - fi - case "$OPERATION" in - deploy) - [[ -z "$EXPECTED_CURRENT_IMAGE_REF" ]] || exit 1 - if [[ "$RUNTIME_SPEC" == runtime=preserve ]]; then - remote_command="deploy ${IMAGE_REF} runtime=preserve" - else - remote_command="deploy ${IMAGE_REF} ${CINDY_ROLLOUT}" - if [[ "$RESOURCE_SPEC" != resource=preserve ]]; then - remote_command+=" $RESOURCE_SPEC" - fi - if [[ -n "$MAINTENANCE_SPEC" ]]; then - remote_command+=" $MAINTENANCE_SPEC" - fi - fi - ;; - reconcile-runtime) - [[ -z "$EXPECTED_CURRENT_IMAGE_REF" ]] || exit 1 - [[ "$RUNTIME_SPEC" == runtime=explicit ]] || exit 1 - remote_command="reconcile-runtime ${IMAGE_REF} ${CINDY_ROLLOUT}" - if [[ -n "$MAINTENANCE_SPEC" ]]; then - remote_command+=" $MAINTENANCE_SPEC" - fi - ;; - rollback) - [[ "$EXPECTED_CURRENT_IMAGE_REF" =~ ^ghcr\.io/htexplicit/sub2api:[0-9]+\.[0-9]+\.[0-9]+-codexrip\.[1-9][0-9]*@sha256:[0-9a-f]{64}$ ]] || exit 1 - [[ "$EXPECTED_CURRENT_IMAGE_REF" != "$IMAGE_REF" ]] || exit 1 - [[ "$RESOURCE_SPEC" == resource=preserve ]] || exit 1 - if [[ "$RUNTIME_SPEC" == runtime=preserve ]]; then - remote_command="rollback ${IMAGE_REF} from=${EXPECTED_CURRENT_IMAGE_REF} runtime=preserve" - else - remote_command="rollback ${IMAGE_REF} from=${EXPECTED_CURRENT_IMAGE_REF} ${CINDY_ROLLOUT}" - fi - ;; - *) - echo 'Operation must be deploy, reconcile-runtime, or rollback' >&2 - exit 1 - ;; - esac + remote_command="deploy ${IMAGE_REF}" ssh \ -F /dev/null \ -i ~/.ssh/sub2api_deploy \ diff --git a/.github/workflows/upstream-auto-deploy.yml b/.github/workflows/upstream-auto-deploy.yml index fb0a35e88ace..f05e77adde15 100644 --- a/.github/workflows/upstream-auto-deploy.yml +++ b/.github/workflows/upstream-auto-deploy.yml @@ -62,12 +62,13 @@ jobs: shell: bash run: | set -euo pipefail - title="Deploy ${RELEASE_TAG} (preserve)" + title="Deploy ${RELEASE_TAG}" + # Reuse deployments already dispatched before the form changed. + legacy_title="${title} (preserve)" existing=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow production-deploy.yml --event workflow_dispatch --limit 50 \ - --json displayTitle --jq "[.[] | select(.displayTitle == \"${title}\")] | length") + --json displayTitle --jq "[.[] | select(.displayTitle == \"${title}\" or .displayTitle == \"${legacy_title}\")] | length") [[ "$existing" == 0 ]] || exit 0 gh workflow run production-deploy.yml --repo "$GITHUB_REPOSITORY" --ref main \ - -f operation=deploy-preserve \ -f release_tag="$RELEASE_TAG" \ -f confirmation=DEPLOY diff --git a/DOWNSTREAM.md b/DOWNSTREAM.md index de3175c88c13..654e2a8e822d 100644 --- a/DOWNSTREAM.md +++ b/DOWNSTREAM.md @@ -62,8 +62,9 @@ The three `238_*` migrations retain separate filenames and checksums. - Downstream Release authenticates to GHCR, verifies source/build materials and publishes the native host image digest and provenance. It reuses PR validation. - Production Deploy resolves the fixed digest through the existing restricted SSH - updater. Ordinary updates use `operation=deploy-preserve`, preserving runtime - settings and resources, naturally draining requests, and rebuilding only Sub2API. + updater. Its only inputs are `release_tag` and `confirmation=DEPLOY`; the host + retains runtime settings and resources, naturally drains requests, and rebuilds + only Sub2API. An older tag uses the same form and requires compatible migrations. - Ordinary updates do not run business backups, canaries, long observation or automatic rollback. A failure preserves the runtime state for diagnosis. - SSH identity checks, fixed image validation, mutual exclusion and command error diff --git a/deploy/README.md b/deploy/README.md index 1d9560709fc3..068ed8c1446b 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -174,111 +174,31 @@ database recovery period is not treated as a permanent process failure. - `schema_migrations` tracks applied migrations (filename + checksum). - Migrations are forward-only; rollback requires a DB backup restore or a manual compensating SQL script. -### Image Studio default and the retained rollout tuple +### Production deployment -`GATEWAY_IMAGE_STUDIO_ENABLED` is the deploy-time default of the Image Studio -switch until an administrator saves the image tool setting; unset or `false` -keeps Image Studio off. Cindy accounts are ordinary OpenAI API-key accounts and -the backend no longer reads any `GATEWAY_CINDY_*` variable. The production -workflow below still carries its historical `cindy=` tuple and the Cindy -platform-v1 label check; the backend ignores those values. - -The protected production workflow exposes the five values as typed boolean -inputs. The platform and jobs phase is dispatched with: - -```bash -gh workflow run production-deploy.yml \ - --repo HTExplicit/sub2api \ - --ref main \ - -f operation=deploy \ - -f release_tag=vX.Y.Z-codexrip.N \ - -f confirmation=DEPLOY \ - -f cindy_health=false \ - -f cindy_capability_catalog=false \ - -f cindy_search=false \ - -f image_studio=false \ - -f cindy_responses_image_bridge=false -``` - -The workflow resolves the release to an immutable digest, requires the Release -body to record that exact image and source commit, and requires the immutable -image's OCI revision and Cindy platform-v1 capability label to match the release. -It sends only `deploy cindy=,,,,` -to the restricted host command. The host persists the tuple in -`/opt/sub2api/docker-compose.cindy-rollout.yml`; a tuple-only change for the -same digest recreates only `sub2api`, with the prior override included in the -checksum-verified rollback set. -During the guard-first migration window, the host accepts only the old workflow's -three-value `cindy=,,` tuple and maps it to the canonical -five-value tuple with Search and Responses-image disabled. -This workflow always emits the explicit five-value tuple. - -If an out-of-band maintenance action recreated `sub2api` from only the base -Compose file while the canonical rollout override remained valid on disk, use -the dedicated reconciliation operation with the exact Release currently -running: +Use the protected production workflow with the immutable release tag and the +exact `DEPLOY` confirmation: ```bash gh workflow run production-deploy.yml \ --repo HTExplicit/sub2api \ --ref main \ - -f operation=reconcile-runtime \ -f release_tag=vX.Y.Z-codexrip.N \ - -f confirmation=RECONCILE \ - -f cindy_health=true \ - -f cindy_capability_catalog=true \ - -f cindy_search=true \ - -f image_studio=false \ - -f cindy_responses_image_bridge=false \ - -f interrupt_business=false -``` - -The host proves that the requested immutable image is already running, the -active container came from base-only Compose, the running tuple matches that -base configuration, and the on-disk canonical override matches the requested -target. It then takes the normal root-only backup and non-target container -snapshot, recreates only `sub2api`, and observes the reconciled runtime for 300 -seconds. Any failure restores the prior base-only runtime; this operation does -not pull or change an image. - -For a controlled stop before recreation, set `-f interrupt_business=true`. The -host appends only `maintenance=interrupt`, stops `sub2api` after the root-only -backup, waits for three stable zero samples of loopback connections and -Redis-backed active leases (up to the fixed 900 second lease grace window), and -then recreates only `sub2api`. A timeout or any post-recreate gate failure -restores the verified base-only runtime and returns a failure status. - -The reconcile path records a fixed same-image native-canary skip marker and does -not create a temporary acceptance credential; all local health, tuple, image, -snapshot, and 300-second observation gates still run. - -An image downgrade uses the same protected `production` Environment and an -explicit expected-current release rather than the deploy path: - -```bash -gh workflow run production-deploy.yml \ - --repo HTExplicit/sub2api \ - --ref main \ - -f operation=rollback \ - -f release_tag=v0.1.177-codexrip.6 \ - -f expected_current_release_tag=v0.1.177-codexrip.7 \ - -f confirmation=ROLLBACK \ - -f cindy_health=true \ - -f cindy_capability_catalog=false \ - -f cindy_search=false \ - -f image_studio=false \ - -f cindy_responses_image_bridge=false + -f confirmation=DEPLOY ``` -The resolver requires both Releases, their recorded immutable references, and -their OCI source revisions to match valid `main` ancestors, and requires -`CURRENT` to be strictly newer than `TARGET`. The forced command is exactly -`rollback from= cindy=...`; the -host rejects it before pulling or mutating state unless the running image is -byte-for-byte equal to `from=`. Ordinary deploys remain unable to downgrade. - -The backend reads only `GATEWAY_IMAGE_STUDIO_ENABLED`; the former -`GATEWAY_CINDY_IMAGE_STUDIO_ENABLED` fallback was removed. +The resolver requires a published stable Release, a release tag on `main`, and +one immutable image reference and source commit in the Release body. The fixed +image's standard OCI revision must match that commit. It sends exactly +`deploy ` to the restricted host command, which naturally drains +requests, changes the image, and recreates only `sub2api`. Runtime settings and +resources remain as configured; container/public health confirms availability, +not actual model functionality. + +An older release uses the same form. Its database migrations must be compatible +with the current data: the workflow does not restore dropped schema or deleted +data and does not automatically roll back a failed deployment. See the migration +boundaries in [native-domains](../.downstream/native-domains.md). **Verify `users.allowed_groups` → `user_allowed_groups` backfill** diff --git a/deploy/tests/production-deploy-workflow-test.sh b/deploy/tests/production-deploy-workflow-test.sh index fef2f40617a8..4db1923926a8 100644 --- a/deploy/tests/production-deploy-workflow-test.sh +++ b/deploy/tests/production-deploy-workflow-test.sh @@ -11,23 +11,29 @@ fail() { exit 1 } -grep -Fq 'packages: read' "$WORKFLOW" || - fail 'production resolve must request GHCR package read permission' +# Authentication, immutable source binding, and the protected deploy job remain. +grep -Fq 'packages: read' "$WORKFLOW" || fail 'resolve must request GHCR read permission' grep -Fq 'docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9' "$WORKFLOW" || - fail 'production resolve must authenticate to GHCR before imagetools inspect' -grep -Fq 'digest="${release_image_ref#${image}@}"' "$WORKFLOW" || - fail 'production resolution must take the immutable digest from the Release body' -grep -Fq 'release_body=$(gh release view "$tag" --json body --jq .body)' "$WORKFLOW" || - fail 'production resolution must read the immutable image reference recorded in the Release body' -grep -Fq '[[ "$release_image_ref" == "${image}@${digest}" ]]' "$WORKFLOW" || - fail 'production resolution must bind the Release digest to the image tag' -grep -Fq 'image_revision=$(docker buildx imagetools inspect "${image}@${digest}" --format' "$WORKFLOW" || - fail 'production resolution must inspect source metadata from the immutable image digest' -grep -Fq '[[ "$image_revision" == "$tag_commit" ]]' "$WORKFLOW" || - fail 'production resolution must bind the immutable image revision to the release tag commit' -if grep -Fq '{print $2; exit}' "$WORKFLOW"; then - fail 'production digest resolution closes the buildx pipe before EOF' + fail 'resolve must authenticate to GHCR' +grep -Fq 'run-name: Deploy ${{ inputs.release_tag }}' "$WORKFLOW" || + fail 'run title must expose the release tag for the status UI' +grep -Fq ' name: production' "$WORKFLOW" || fail 'deployment must use the production environment' +[[ "$(grep -c '^ [a-z_]*:$' "$WORKFLOW")" -eq 2 ]] || fail 'workflow must have only two inputs' +for input in release_tag confirmation; do + grep -Fq " ${input}:" "$WORKFLOW" || fail "missing input: $input" +done +if grep -Eq 'expected_current|runtime=|resource=|CINDY_|IMAGE_STUDIO|INTERRUPT_BUSINESS|rollback|reconcile-runtime|io.github.htexplicit' "$WORKFLOW"; then + fail 'workflow still contains a retired deployment interface or image label gate' +fi +if grep -Fq 'io.github.htexplicit.' "$DOWNSTREAM_RELEASE_WORKFLOW"; then + fail 'release still emits retired fork image labels' fi +for label in source version revision created licenses; do + grep -Fq "org.opencontainers.image.${label}=" "$DOWNSTREAM_RELEASE_WORKFLOW" || + fail "standard OCI label missing: $label" +done +grep -Fq "!contains(github.ref_name, '-codexrip.')" "$GENERIC_RELEASE_WORKFLOW" || + fail 'generic Release must skip downstream codexrip tags' tmpdir=$(mktemp -d) trap 'rm -rf "$tmpdir"' EXIT @@ -38,28 +44,45 @@ awk ' capture && /^ deploy:$/ { exit } capture { sub(/^ /, ""); print } ' "$WORKFLOW" >"$resolve_script" -[[ -s "$resolve_script" ]] || fail 'could not extract the resolve shell step' +[[ -s "$resolve_script" ]] || fail 'could not extract resolve step' apply_script="$tmpdir/apply.sh" awk ' - /^ - name: Apply immutable release operation$/ { found_apply = 1; next } + /^ - name: Apply immutable release image$/ { found_apply = 1; next } found_apply && /^ run: \|$/ { capture = 1; next } capture && /^ - name:/ { exit } capture { sub(/^ /, ""); print } ' "$WORKFLOW" >"$apply_script" -[[ -s "$apply_script" ]] || fail 'could not extract the immutable release operation shell step' +[[ -s "$apply_script" ]] || fail 'could not extract deploy step' +bash -n "$resolve_script" +bash -n "$apply_script" mkdir -p "$tmpdir/bin" cat >"$tmpdir/bin/gh" <<'EOF' #!/usr/bin/env bash set -euo pipefail -if [[ " $* " == *' --json assets '* ]]; then - printf '%s\n' 'seed-descriptor.json' - for ((i = 0; i < 10000; i++)); do - printf 'ordinary-release-asset-%05d-%064d.bin\n' "$i" "$i" - done -elif [[ " $* " == *' --json tagName,isDraft,isPrerelease '* ]]; then - printf '%s\tfalse\tfalse\n' "$3" +tag=$3 +case "$tag" in + v0.1.177-codexrip.6) + digest=sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + source=1111111111111111111111111111111111111111 + ;; + v0.1.177-codexrip.7) + digest=sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + source=2222222222222222222222222222222222222222 + ;; + *) exit 3 ;; +esac +if [[ " $* " == *' --json tagName,isDraft,isPrerelease '* ]]; then + printf '%s\t%s\t%s\n' "$tag" "${MOCK_RELEASE_DRAFT:-false}" "${MOCK_RELEASE_PRERELEASE:-false}" +elif [[ " $* " == *' --json body '* ]]; then + printf 'Image: `%s`\nSource: `%s`\n' \ + "${MOCK_BODY_IMAGE:-ghcr.io/htexplicit/sub2api:${tag#v}@${MOCK_BODY_DIGEST:-$digest}}" \ + "${MOCK_BODY_SOURCE:-$source}" + if [[ "${MOCK_DUPLICATE_IMAGE:-false}" == true ]]; then + printf 'Image: `ghcr.io/htexplicit/sub2api:%s@%s`\n' "${tag#v}" "$digest" + fi else + # No asset inventory or retired Skill gate belongs to deployment resolution. exit 2 fi EOF @@ -67,13 +90,13 @@ cat >"$tmpdir/bin/git" <<'EOF' #!/usr/bin/env bash set -euo pipefail case "$1" in - fetch|merge-base) exit 0 ;; + fetch) exit 0 ;; + merge-base) [[ "${MOCK_NON_ANCESTOR:-false}" == false ]] ;; rev-list) tag=${!#} case "$tag" in v0.1.177-codexrip.6) printf '%s\n' 1111111111111111111111111111111111111111 ;; v0.1.177-codexrip.7) printf '%s\n' 2222222222222222222222222222222222222222 ;; - v0.1.177-codexrip.8) printf '%s\n' 3333333333333333333333333333333333333333 ;; *) exit 3 ;; esac ;; @@ -83,489 +106,125 @@ EOF cat >"$tmpdir/bin/docker" <<'EOF' #!/usr/bin/env bash set -euo pipefail -printf 'Name: image\nDigest: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n' -EOF -chmod +x "$tmpdir/bin/gh" "$tmpdir/bin/git" "$tmpdir/bin/docker" - -set +e -PATH="$tmpdir/bin:$PATH" \ -OPERATION=deploy \ -RELEASE_TAG=v0.1.177-codexrip.7 \ -EXPECTED_CURRENT_RELEASE_TAG= \ -CONFIRMATION=DEPLOY \ -CINDY_HEALTH=true \ -CINDY_CAPABILITY_CATALOG=false \ - CINDY_SEARCH=false \ - IMAGE_STUDIO=false \ - CINDY_RESPONSES_IMAGE_BRIDGE=false \ - INTERRUPT_BUSINESS=false \ - GITHUB_OUTPUT="$tmpdir/github-output" \ -bash "$resolve_script" >"$tmpdir/resolve-output" 2>&1 -resolve_status=$? -set -e -[[ "$resolve_status" -ne 0 ]] || - fail 'removed release asset was accepted when the producer received SIGPIPE' -grep -Fq 'contains a removed Skill-specific asset' "$tmpdir/resolve-output" || - fail 'removed release asset did not fail through the intended release gate' - -cat >"$tmpdir/bin/gh" <<'EOF' -#!/usr/bin/env bash -set -euo pipefail -tag=$3 -case "$tag" in - v0.1.177-codexrip.6) - digest=sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - source=1111111111111111111111111111111111111111 - ;; - v0.1.177-codexrip.7) - digest=sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - source=2222222222222222222222222222222222222222 - ;; - v0.1.177-codexrip.8) - digest=sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - source=3333333333333333333333333333333333333333 - ;; - *) exit 3 ;; -esac -if [[ "${MOCK_OVERRIDE_TAG:-}" == "$tag" ]]; then - digest=${MOCK_BODY_DIGEST_OVERRIDE:-$digest} - source=${MOCK_BODY_SOURCE_OVERRIDE:-$source} -fi -if [[ " $* " == *' --json assets '* ]]; then - printf '%s\n' 'sub2api-release-checksums.txt' -elif [[ " $* " == *' --json tagName,isDraft,isPrerelease '* ]]; then - draft=false - prerelease=false - if [[ "${MOCK_OVERRIDE_TAG:-}" == "$tag" ]]; then - draft=${MOCK_RELEASE_DRAFT_OVERRIDE:-false} - prerelease=${MOCK_RELEASE_PRERELEASE_OVERRIDE:-false} - fi - printf '%s\t%s\t%s\n' "$tag" "$draft" "$prerelease" -elif [[ " $* " == *' --json body '* ]]; then - version=${tag#v} - printf 'Image: `ghcr.io/htexplicit/sub2api:%s@%s`\nSource: `%s`\n' "$version" "$digest" "$source" -else - exit 2 -fi -EOF -cat >"$tmpdir/bin/docker" <<'EOF' -#!/usr/bin/env bash -set -euo pipefail image_ref=$4 case "$image_ref" in *:0.1.177-codexrip.6*) - tag=v0.1.177-codexrip.6 digest=sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa revision=1111111111111111111111111111111111111111 - platform_v1=false ;; *:0.1.177-codexrip.7*) - tag=v0.1.177-codexrip.7 digest=sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb revision=2222222222222222222222222222222222222222 - platform_v1=true - ;; - *:0.1.177-codexrip.8*) - tag=v0.1.177-codexrip.8 - digest=sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - revision=3333333333333333333333333333333333333333 - platform_v1=true ;; *) exit 3 ;; esac -if [[ "${MOCK_OVERRIDE_TAG:-}" == "$tag" ]]; then - digest=${MOCK_REGISTRY_DIGEST_OVERRIDE:-$digest} - revision=${MOCK_IMAGE_REVISION_OVERRIDE:-$revision} - platform_v1=${MOCK_IMAGE_PLATFORM_V1_OVERRIDE:-$platform_v1} -fi -if [[ "$image_ref" == *@sha256:* ]]; then - requested=${image_ref##*@} - [[ "$requested" == "$digest" ]] || exit 3 -fi -if [[ " $* " == *'io.github.htexplicit.cindy-platform-v1'* ]]; then - printf '%s\n' "$platform_v1" -elif [[ " $* " == *' --format '* ]]; then - printf '%s\n' "$revision" -else - printf 'Name: image\nDigest: %s\n' "$digest" -fi +[[ "$image_ref" == *@"$digest" ]] || exit 3 +[[ "$6" == '{{ index .Image.Config.Labels "org.opencontainers.image.revision" }}' ]] || exit 2 +printf '%s\n' "${MOCK_IMAGE_REVISION:-$revision}" EOF cat >"$tmpdir/bin/ssh" <<'EOF' #!/usr/bin/env bash set -euo pipefail -: "${SSH_CAPTURE:?}" -: "${SSH_CALLS:?}" -printf 'call\n' >>"$SSH_CALLS" -printf '%s\n' "$@" >"$SSH_CAPTURE" +printf 'call\n' >>"${SSH_CALLS:?}" +printf '%s\n' "$@" >"${SSH_CAPTURE:?}" EOF -chmod +x "$tmpdir/bin/gh" "$tmpdir/bin/docker" "$tmpdir/bin/ssh" +chmod +x "$tmpdir/bin/gh" "$tmpdir/bin/git" "$tmpdir/bin/docker" "$tmpdir/bin/ssh" run_resolve() { - local operation=$1 tag=$2 expected_current=$3 confirmation=$4 interrupt=${5-false} : >"$tmpdir/github-output" - : >"$tmpdir/resolve-output" PATH="$tmpdir/bin:$PATH" \ - MOCK_OVERRIDE_TAG="${MOCK_OVERRIDE_TAG:-}" \ - MOCK_RELEASE_DRAFT_OVERRIDE="${MOCK_RELEASE_DRAFT_OVERRIDE:-}" \ - MOCK_RELEASE_PRERELEASE_OVERRIDE="${MOCK_RELEASE_PRERELEASE_OVERRIDE:-}" \ - MOCK_BODY_DIGEST_OVERRIDE="${MOCK_BODY_DIGEST_OVERRIDE:-}" \ - MOCK_BODY_SOURCE_OVERRIDE="${MOCK_BODY_SOURCE_OVERRIDE:-}" \ - MOCK_REGISTRY_DIGEST_OVERRIDE="${MOCK_REGISTRY_DIGEST_OVERRIDE:-}" \ - MOCK_IMAGE_REVISION_OVERRIDE="${MOCK_IMAGE_REVISION_OVERRIDE:-}" \ - MOCK_IMAGE_PLATFORM_V1_OVERRIDE="${MOCK_IMAGE_PLATFORM_V1_OVERRIDE:-}" \ - OPERATION="$operation" \ - RELEASE_TAG="$tag" \ - EXPECTED_CURRENT_RELEASE_TAG="$expected_current" \ - CONFIRMATION="$confirmation" \ - CINDY_HEALTH=true \ - CINDY_CAPABILITY_CATALOG=false \ - CINDY_SEARCH=false \ - IMAGE_STUDIO=false \ - CINDY_RESPONSES_IMAGE_BRIDGE=false \ - INTERRUPT_BUSINESS="$interrupt" \ - GITHUB_OUTPUT="$tmpdir/github-output" \ + MOCK_RELEASE_DRAFT="${MOCK_RELEASE_DRAFT:-false}" \ + MOCK_RELEASE_PRERELEASE="${MOCK_RELEASE_PRERELEASE:-false}" \ + MOCK_BODY_DIGEST="${MOCK_BODY_DIGEST:-}" \ + MOCK_BODY_IMAGE="${MOCK_BODY_IMAGE:-}" \ + MOCK_BODY_SOURCE="${MOCK_BODY_SOURCE:-}" \ + MOCK_DUPLICATE_IMAGE="${MOCK_DUPLICATE_IMAGE:-false}" \ + MOCK_IMAGE_REVISION="${MOCK_IMAGE_REVISION:-}" \ + MOCK_NON_ANCESTOR="${MOCK_NON_ANCESTOR:-false}" \ + RELEASE_TAG="$1" CONFIRMATION="$2" GITHUB_OUTPUT="$tmpdir/github-output" \ bash "$resolve_script" >"$tmpdir/resolve-output" 2>&1 } -run_apply() { - local operation=$1 image_ref=$2 expected_current=$3 rollout=$4 runtime_spec=${5-runtime=explicit} maintenance_spec=${6-} - : >"$tmpdir/ssh-capture" - : >"$tmpdir/ssh-calls" - : >"$tmpdir/apply-output" - HOME="$tmpdir/home" \ - PATH="$tmpdir/bin:$PATH" \ - SSH_CAPTURE="$tmpdir/ssh-capture" \ - SSH_CALLS="$tmpdir/ssh-calls" \ - VPS_HOST=production.example.invalid \ - VPS_PORT="${MOCK_VPS_PORT:-2222}" \ - VPS_USER=deployer \ - OPERATION="$operation" \ - IMAGE_REF="$image_ref" \ - EXPECTED_CURRENT_IMAGE_REF="$expected_current" \ - CINDY_ROLLOUT="$rollout" \ - MAINTENANCE_SPEC="$maintenance_spec" \ - RUNTIME_SPEC="$runtime_spec" \ - bash "$apply_script" >"$tmpdir/apply-output" 2>&1 -} - -assert_ssh_invocation() { - local expected_remote_command=$1 index line - local -a actual expected - actual=() - while IFS= read -r line; do - actual+=("$line") - done <"$tmpdir/ssh-capture" - expected=( - -F /dev/null - -i "$tmpdir/home/.ssh/sub2api_deploy" - -o BatchMode=yes - -o IdentitiesOnly=yes - -o ServerAliveInterval=30 - -o ServerAliveCountMax=10 - -o StrictHostKeyChecking=yes - -o "UserKnownHostsFile=$tmpdir/home/.ssh/known_hosts" - -p 2222 - deployer@production.example.invalid - "$expected_remote_command" - ) - [[ "$(wc -l <"$tmpdir/ssh-calls")" -eq 1 ]] || - fail 'immutable release operation did not invoke ssh exactly once' - [[ "${#actual[@]}" -eq "${#expected[@]}" ]] || - fail "ssh argv length mismatch: expected ${#expected[@]}, got ${#actual[@]}" - for ((index = 0; index < ${#expected[@]}; index++)); do - [[ "${actual[$index]}" == "${expected[$index]}" ]] || - fail "ssh argv[$index] mismatch: expected '${expected[$index]}', got '${actual[$index]}'" - done -} - -assert_ssh_not_invoked() { - [[ ! -s "$tmpdir/ssh-calls" && ! -s "$tmpdir/ssh-capture" ]] || - fail 'rejected immutable release operation still invoked ssh' +assert_resolve_rejected() { + if run_resolve "$1" "$2"; then fail "$3"; fi + [[ ! -s "$tmpdir/github-output" ]] || fail 'rejected release emitted a deployable image' } -rollback_target_ref=ghcr.io/htexplicit/sub2api:0.1.177-codexrip.6@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -rollback_current_ref=ghcr.io/htexplicit/sub2api:0.1.177-codexrip.7@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - -if ! run_resolve deploy v0.1.177-codexrip.7 '' DEPLOY; then - cat "$tmpdir/resolve-output" >&2 - fail 'valid deploy resolution did not execute successfully' -fi -grep -Fq "image_ref=$rollback_current_ref" "$tmpdir/github-output" || - fail 'deploy did not emit the Release-bound immutable image' -grep -Fxq 'expected_current_image_ref=' "$tmpdir/github-output" || - fail 'deploy unexpectedly emitted an expected-current rollback image' - -if ! run_resolve reconcile-runtime v0.1.177-codexrip.7 '' RECONCILE; then - cat "$tmpdir/resolve-output" >&2 - fail 'valid runtime reconciliation did not resolve successfully' -fi -grep -Fq "image_ref=$rollback_current_ref" "$tmpdir/github-output" || - fail 'runtime reconciliation did not resolve its exact current Release image' -grep -Fxq 'expected_current_image_ref=' "$tmpdir/github-output" || - fail 'runtime reconciliation unexpectedly emitted a second current image' -grep -Fxq 'operation=reconcile-runtime' "$tmpdir/github-output" || - fail 'runtime reconciliation did not preserve its dedicated operation' -grep -Fxq 'runtime_spec=runtime=explicit' "$tmpdir/github-output" || - fail 'runtime reconciliation did not require an explicit target runtime tuple' -if run_resolve reconcile-runtime v0.1.177-codexrip.7 '' DEPLOY; then - fail 'runtime reconciliation accepted the deploy confirmation word' -fi -if run_resolve reconcile-runtime v0.1.177-codexrip.7 v0.1.177-codexrip.6 RECONCILE; then - fail 'runtime reconciliation accepted a separate expected-current release' -fi -if ! run_resolve reconcile-runtime v0.1.177-codexrip.7 '' RECONCILE true; then - cat "$tmpdir/resolve-output" >&2 - fail 'runtime reconciliation rejected the explicit interruption mode' -fi -grep -Fxq 'maintenance_spec=maintenance=interrupt' "$tmpdir/github-output" || - fail 'runtime reconciliation did not emit the explicit interruption spec' - -run_resolve deploy v0.1.177-codexrip.7 '' DEPLOY true || - fail 'deploy resolution rejected the explicit interruption mode' -grep -Fxq 'maintenance_spec=maintenance=interrupt' "$tmpdir/github-output" || - fail 'deploy resolution did not emit the explicit interruption spec' - -run_resolve rollback v0.1.177-codexrip.6 v0.1.177-codexrip.7 ROLLBACK || - fail 'valid rollback resolution did not execute successfully' -grep -Fq "image_ref=$rollback_target_ref" "$tmpdir/github-output" || - fail 'rollback did not emit the immutable target image' -grep -Fq "expected_current_image_ref=$rollback_current_ref" "$tmpdir/github-output" || - fail 'rollback did not emit the immutable expected-current image' - -MOCK_OVERRIDE_TAG=v0.1.177-codexrip.7 -MOCK_BODY_DIGEST_OVERRIDE=sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd -if run_resolve deploy v0.1.177-codexrip.7 '' DEPLOY; then - fail 'registry digest was accepted when it did not match the Release body' -fi -unset MOCK_BODY_DIGEST_OVERRIDE -MOCK_BODY_SOURCE_OVERRIDE=4444444444444444444444444444444444444444 -if run_resolve deploy v0.1.177-codexrip.7 '' DEPLOY; then - fail 'Release source was accepted when it did not match the release tag commit' -fi -unset MOCK_BODY_SOURCE_OVERRIDE -MOCK_IMAGE_REVISION_OVERRIDE=4444444444444444444444444444444444444444 -if run_resolve deploy v0.1.177-codexrip.7 '' DEPLOY; then - fail 'immutable image was accepted when its OCI revision did not match the release tag commit' -fi -unset MOCK_IMAGE_REVISION_OVERRIDE -MOCK_IMAGE_PLATFORM_V1_OVERRIDE=false -if run_resolve deploy v0.1.177-codexrip.7 '' DEPLOY; then - fail 'immutable image without the Cindy platform-v1 capability label was accepted' -fi -unset MOCK_IMAGE_PLATFORM_V1_OVERRIDE -MOCK_RELEASE_DRAFT_OVERRIDE=true -if run_resolve deploy v0.1.177-codexrip.7 '' DEPLOY; then - fail 'draft Release was accepted for production deploy' -fi -unset MOCK_RELEASE_DRAFT_OVERRIDE MOCK_OVERRIDE_TAG - -MOCK_OVERRIDE_TAG=v0.1.177-codexrip.7 -MOCK_BODY_DIGEST_OVERRIDE=sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd -if run_resolve rollback v0.1.177-codexrip.6 v0.1.177-codexrip.7 ROLLBACK; then - fail 'rollback accepted an expected-current Release body with the wrong digest' -fi -unset MOCK_BODY_DIGEST_OVERRIDE -MOCK_BODY_SOURCE_OVERRIDE=4444444444444444444444444444444444444444 -if run_resolve rollback v0.1.177-codexrip.6 v0.1.177-codexrip.7 ROLLBACK; then - fail 'rollback accepted an expected-current Release body with the wrong source' -fi -unset MOCK_BODY_SOURCE_OVERRIDE -MOCK_IMAGE_REVISION_OVERRIDE=4444444444444444444444444444444444444444 -if run_resolve rollback v0.1.177-codexrip.6 v0.1.177-codexrip.7 ROLLBACK; then - fail 'rollback accepted an expected-current image with the wrong OCI revision' -fi -unset MOCK_IMAGE_REVISION_OVERRIDE -MOCK_IMAGE_PLATFORM_V1_OVERRIDE=false -if run_resolve rollback v0.1.177-codexrip.6 v0.1.177-codexrip.7 ROLLBACK; then - fail 'rollback accepted an expected-current image without the platform-v1 capability label' -fi -unset MOCK_IMAGE_PLATFORM_V1_OVERRIDE MOCK_OVERRIDE_TAG -if run_resolve rollback v0.1.177-codexrip.8 v0.1.177-codexrip.7 ROLLBACK; then - fail 'rollback target newer than expected-current was accepted' -fi -if run_resolve rollback v0.1.177-codexrip.6 v0.1.177-codexrip.7 ROLLBACK true; then - fail 'rollback accepted the business interruption mode' -fi - -run_apply deploy "$rollback_current_ref" '' 'cindy=true,true,true,false,false' || - fail 'valid deploy operation did not execute successfully' -assert_ssh_invocation "deploy $rollback_current_ref cindy=true,true,true,false,false" - -run_apply rollback "$rollback_target_ref" "$rollback_current_ref" 'cindy=true,false,false,false,false' || - fail 'valid rollback operation did not execute successfully' -assert_ssh_invocation "rollback $rollback_target_ref from=$rollback_current_ref cindy=true,false,false,false,false" - -run_apply deploy "$rollback_current_ref" '' 'cindy=true,true,true,false,false' runtime=explicit maintenance=interrupt || - fail 'valid maintenance-interrupt deploy operation did not execute successfully' -assert_ssh_invocation "deploy $rollback_current_ref cindy=true,true,true,false,false maintenance=interrupt" - -run_apply deploy "$rollback_current_ref" '' '' runtime=preserve || - fail 'valid runtime-preserve deploy operation did not execute successfully' -assert_ssh_invocation "deploy $rollback_current_ref runtime=preserve" - -run_apply reconcile-runtime "$rollback_current_ref" '' 'cindy=true,true,true,false,false' || - fail 'valid runtime reconciliation did not execute successfully' -assert_ssh_invocation "reconcile-runtime $rollback_current_ref cindy=true,true,true,false,false" - -run_apply reconcile-runtime "$rollback_current_ref" '' 'cindy=true,true,true,false,false' runtime=explicit maintenance=interrupt || - fail 'valid interrupted runtime reconciliation did not execute successfully' -assert_ssh_invocation "reconcile-runtime $rollback_current_ref cindy=true,true,true,false,false maintenance=interrupt" - -if run_apply reconcile-runtime "$rollback_current_ref" "$rollback_target_ref" 'cindy=true,true,true,false,false'; then - fail 'runtime reconciliation accepted a second expected-current image' -fi -assert_ssh_not_invoked -if run_apply reconcile-runtime "$rollback_current_ref" '' 'cindy=true,true,true,false,false' runtime=preserve; then - fail 'runtime reconciliation accepted runtime-preserve mode' -fi -assert_ssh_not_invoked -if run_apply deploy "$rollback_current_ref" "$rollback_target_ref" 'cindy=true,true,true,false,false'; then - fail 'deploy accepted an unexpected expected-current image' -fi -assert_ssh_not_invoked -if run_apply rollback "$rollback_target_ref" "$rollback_target_ref" 'cindy=true,false,false,false,false'; then - fail 'rollback accepted a target equal to expected-current' -fi -assert_ssh_not_invoked -MOCK_VPS_PORT=not-a-port -if run_apply deploy "$rollback_current_ref" '' 'cindy=true,true,true,false,false'; then - fail 'deploy accepted a malformed SSH port' -fi -unset MOCK_VPS_PORT -assert_ssh_not_invoked -if run_apply deploy 'ghcr.io/htexplicit/sub2api:latest' '' 'cindy=true,true,true,false,false'; then - fail 'deploy accepted a mutable image reference' -fi -assert_ssh_not_invoked -if run_apply deploy "$rollback_current_ref" '' 'cindy=true,false,true'; then - fail 'deploy accepted a malformed Cindy rollout' -fi -assert_ssh_not_invoked -if run_apply rollback "$rollback_target_ref" '' 'cindy=true,false,false,false,false'; then - fail 'rollback accepted an empty expected-current image' -fi -assert_ssh_not_invoked -if run_apply invalid "$rollback_current_ref" '' 'cindy=true,true,true,false,false'; then - fail 'immutable release operation accepted an unknown operation' -fi -assert_ssh_not_invoked - -inspect=$'Name: image\nDigest: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\nManifest: amd64\nManifest: attestation' -digest=$(awk '$1 == "Digest:" && digest == "" {digest=$2} END {if (digest == "") exit 1; print digest}' <<<"$inspect") -[[ "$digest" == 'sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ]] || - fail 'digest parser did not preserve the first index digest' - -for input in operation release_tag expected_current_release_tag confirmation \ - cindy_health cindy_capability_catalog cindy_search image_studio \ - cindy_responses_image_bridge interrupt_business resource_profile; do - grep -Fq " ${input}:" "$WORKFLOW" || fail "missing typed workflow input: $input" +# Both old and new immutable images use the same path, without fork labels. +for tag in v0.1.177-codexrip.6 v0.1.177-codexrip.7; do + run_resolve "$tag" DEPLOY || { cat "$tmpdir/resolve-output" >&2; fail 'valid release was rejected'; } + [[ "$(wc -l <"$tmpdir/github-output")" -eq 1 ]] || fail 'resolve must emit only image_ref' + grep -Fq "image_ref=ghcr.io/htexplicit/sub2api:${tag#v}@sha256:" "$tmpdir/github-output" || + fail 'resolve did not emit the immutable release image' done -grep -Fq ' - deploy' "$WORKFLOW" || fail 'workflow operation is missing deploy' -grep -Fq ' - deploy-preserve' "$WORKFLOW" || fail 'workflow operation is missing deploy-preserve' -grep -Fq ' - reconcile-runtime' "$WORKFLOW" || fail 'workflow operation is missing reconcile-runtime' -grep -Fq ' - rollback' "$WORKFLOW" || fail 'workflow operation is missing rollback' -[[ "$(grep -c ' type: boolean' "$WORKFLOW")" -ge 5 ]] || - fail 'Cindy rollout inputs must be typed booleans' -[[ "$(grep -c ' default: false' "$WORKFLOW")" -ge 5 ]] || - fail 'all staged rollout phases must default off' -if grep -Fq 'requires the Cindy capability catalog' "$WORKFLOW"; then - fail 'independent Search, Image Studio, or Responses-image flags still depend on the catalog' -fi -grep -Fq 'cindy_rollout=cindy=${CINDY_HEALTH},${CINDY_CAPABILITY_CATALOG},${CINDY_SEARCH},${IMAGE_STUDIO},${CINDY_RESPONSES_IMAGE_BRIDGE}' "$WORKFLOW" || - fail 'resolve must emit a canonical Cindy rollout tuple' -grep -Fq 'io.github.htexplicit.cindy-platform-v1' "$WORKFLOW" || - fail 'resolve must require the platform capability label from the immutable image' -grep -Fq 'expected_current_image_ref=${expected_current_image_ref}' "$WORKFLOW" || - fail 'resolve must publish the immutable expected-current rollback image' -grep -Fq '[[ "$CONFIRMATION" == DEPLOY ]]' "$WORKFLOW" || - fail 'deploy must require the exact DEPLOY confirmation' -grep -Fq '[[ "$CONFIRMATION" == ROLLBACK ]]' "$WORKFLOW" || - fail 'rollback must require the exact ROLLBACK confirmation' -grep -Fq '[[ "$CONFIRMATION" == RECONCILE ]]' "$WORKFLOW" || - fail 'runtime reconciliation must require the exact RECONCILE confirmation' -grep -Fq 'resolve_release_image "$EXPECTED_CURRENT_RELEASE_TAG"' "$WORKFLOW" || - fail 'rollback must independently resolve the expected-current release image' -grep -Fq 'resolve_release_image "$RELEASE_TAG" rollback-target' "$WORKFLOW" || - fail 'rollback must resolve the target using the legacy-aware image role' -grep -Fq 'resolve_release_image "$EXPECTED_CURRENT_RELEASE_TAG" platform' "$WORKFLOW" || - fail 'rollback must require the expected-current image to be platform capable' -grep -Fq 'isDraft,isPrerelease' "$WORKFLOW" || - fail 'release state resolution must inspect draft and prerelease flags' -grep -Fq '\tfalse\tfalse' "$WORKFLOW" || - fail 'deploy and rollback releases must be published and non-prerelease' -grep -Fq 'version_strictly_less "$RELEASE_TAG" "$EXPECTED_CURRENT_RELEASE_TAG"' "$WORKFLOW" || - fail 'rollback must require the target release to be older than expected-current' -grep -Fq 'remote_command="deploy ${IMAGE_REF} ${CINDY_ROLLOUT}"' "$WORKFLOW" || - fail 'deploy must pass the canonical rollout tuple to the forced command' -grep -Fq 'remote_command+=" $RESOURCE_SPEC"' "$WORKFLOW" || - fail 'deploy must pass an explicit Sub2API resource profile to the forced command' -grep -Fq 'maintenance_spec=maintenance=interrupt' "$WORKFLOW" || - fail 'explicit business interruption must resolve to a fixed maintenance spec' -grep -Fq 'remote_command+=" $MAINTENANCE_SPEC"' "$WORKFLOW" || - fail 'explicit business interruption must be appended only after validation' -grep -Fq '[[ "$OPERATION" == deploy || "$OPERATION" == reconcile-runtime || -z "$MAINTENANCE_SPEC" ]]' "$WORKFLOW" || - fail 'rollback must reject the maintenance interrupt spec while allowing deploy/reconcile' -grep -Fq '[[ "$INTERRUPT_BUSINESS" == false ]]' "$WORKFLOW" || - fail 'preserve/rollback paths must reject business interruption' -grep -Fq 'remote_command="deploy ${IMAGE_REF} runtime=preserve"' "$WORKFLOW" || - fail 'automatic deploy must preserve the locked runtime tuple' -grep -Fq 'remote_command="reconcile-runtime ${IMAGE_REF} ${CINDY_ROLLOUT}"' "$WORKFLOW" || - fail 'runtime reconciliation must bind the exact current image and explicit runtime tuple' -grep -Fq 'remote_command+=" $MAINTENANCE_SPEC"' "$WORKFLOW" || - fail 'runtime reconciliation must append only the validated maintenance interrupt spec' -grep -Fq 'if [[ ("$OPERATION" == deploy || "$OPERATION" == reconcile-runtime) && "$INTERRUPT_BUSINESS" == true ]]; then' "$WORKFLOW" || - fail 'runtime reconciliation interruption was not bound to the fixed maintenance spec' -grep -Fq 'remote_command="rollback ${IMAGE_REF} from=${EXPECTED_CURRENT_IMAGE_REF} ${CINDY_ROLLOUT}"' "$WORKFLOW" || - fail 'rollback must bind the target to the exact expected-current image' - -validate_rollout() { - local value=$1 - [[ "$value" =~ ^cindy=(true|false),(true|false),(true|false),(true|false),(true|false)$ ]] -} - -validate_rollout 'cindy=false,false,false,false,false' || fail 'platform-only rollout was rejected' -validate_rollout 'cindy=false,true,false,false,false' || fail 'catalog rollout was rejected' -validate_rollout 'cindy=true,true,false,false,false' || fail 'health rollout was rejected' -validate_rollout 'cindy=true,true,true,false,false' || fail 'search rollout was rejected' -validate_rollout 'cindy=true,true,true,true,false' || fail 'Image Studio rollout was rejected' -validate_rollout 'cindy=true,true,true,true,true' || fail 'Responses-image rollout was rejected' -validate_rollout 'cindy=false,false,true,true,true' || fail 'independent feature rollout was rejected' -for invalid in \ - 'cindy=1,false,false,false,false' \ - 'cindy=true,false,false,false,false extra' \ - 'cindy=true,false,false,false,false;id' \ - 'cindy=true, true,false,false,false' \ - 'cindy=true,false,false' -do - if validate_rollout "$invalid"; then - fail "malformed rollout tuple was accepted: $invalid" - fi +for confirmation in ROLLBACK RECONCILE deploy ''; do + assert_resolve_rejected v0.1.177-codexrip.7 "$confirmation" 'non-DEPLOY confirmation was accepted' done +for tag in latest v0.1.177 v0.1.177-codexrip.0 'v0.1.177-codexrip.7;id'; do + assert_resolve_rejected "$tag" DEPLOY 'invalid release tag was accepted' +done +MOCK_RELEASE_DRAFT=true +assert_resolve_rejected v0.1.177-codexrip.7 DEPLOY 'draft release was accepted' +unset MOCK_RELEASE_DRAFT +MOCK_RELEASE_PRERELEASE=true +assert_resolve_rejected v0.1.177-codexrip.7 DEPLOY 'prerelease was accepted' +unset MOCK_RELEASE_PRERELEASE +MOCK_BODY_DIGEST=sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd +assert_resolve_rejected v0.1.177-codexrip.7 DEPLOY 'unavailable release digest was accepted' +unset MOCK_BODY_DIGEST +MOCK_BODY_IMAGE=ghcr.io/htexplicit/sub2api:latest +assert_resolve_rejected v0.1.177-codexrip.7 DEPLOY 'wrong image tag was accepted' +unset MOCK_BODY_IMAGE +MOCK_BODY_SOURCE=4444444444444444444444444444444444444444 +assert_resolve_rejected v0.1.177-codexrip.7 DEPLOY 'release source mismatch was accepted' +unset MOCK_BODY_SOURCE +MOCK_IMAGE_REVISION=4444444444444444444444444444444444444444 +assert_resolve_rejected v0.1.177-codexrip.7 DEPLOY 'OCI revision mismatch was accepted' +unset MOCK_IMAGE_REVISION +MOCK_DUPLICATE_IMAGE=true +assert_resolve_rejected v0.1.177-codexrip.7 DEPLOY 'ambiguous release body was accepted' +unset MOCK_DUPLICATE_IMAGE +MOCK_NON_ANCESTOR=true +assert_resolve_rejected v0.1.177-codexrip.7 DEPLOY 'release outside main was accepted' +unset MOCK_NON_ANCESTOR -grep -Fq 'io.github.htexplicit.cindy-platform-v1=true' "$DOWNSTREAM_RELEASE_WORKFLOW" || - fail 'downstream image must declare the platform capability label' -grep -Fq "!contains(github.ref_name, '-codexrip.')" "$GENERIC_RELEASE_WORKFLOW" || - fail 'generic Release workflow must skip downstream codexrip tags' - -version_strictly_less() { - local target=$1 current=$2 first - [[ "$target" != "$current" ]] || return 1 - first=$(printf '%s\n%s\n' "$target" "$current" | LC_ALL=C sort -V | head -n 1) - [[ "$first" == "$target" ]] +run_apply() { + : >"$tmpdir/ssh-capture" + : >"$tmpdir/ssh-calls" + PATH="$tmpdir/bin:$PATH" SSH_CAPTURE="$tmpdir/ssh-capture" SSH_CALLS="$tmpdir/ssh-calls" \ + VPS_HOST=production.example.invalid VPS_PORT="${MOCK_VPS_PORT:-2222}" VPS_USER=deployer \ + IMAGE_REF="$1" bash "$apply_script" >"$tmpdir/apply-output" 2>&1 } -version_strictly_less 'v0.1.177-codexrip.6' 'v0.1.177-codexrip.7' || - fail 'valid rollback order was rejected' -version_strictly_less 'v0.1.176-codexrip.16' 'v0.1.177-codexrip.1' || - fail 'valid cross-upstream rollback order was rejected' -for invalid_pair in \ - 'v0.1.177-codexrip.7 v0.1.177-codexrip.7' \ - 'v0.1.177-codexrip.8 v0.1.177-codexrip.7' \ - 'v0.1.178-codexrip.1 v0.1.177-codexrip.9'; do - read -r target current <<<"$invalid_pair" - if version_strictly_less "$target" "$current"; then - fail "unsafe rollback order was accepted: $invalid_pair" - fi +image_ref=ghcr.io/htexplicit/sub2api:0.1.177-codexrip.7@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +run_apply "$image_ref" || fail 'valid deploy did not execute' +actual=() +while IFS= read -r line; do actual+=("$line"); done <"$tmpdir/ssh-capture" +expected=( + -F /dev/null + -i "$HOME/.ssh/sub2api_deploy" + -o BatchMode=yes + -o IdentitiesOnly=yes + -o ServerAliveInterval=30 + -o ServerAliveCountMax=10 + -o StrictHostKeyChecking=yes + -o "UserKnownHostsFile=$HOME/.ssh/known_hosts" + -p 2222 + deployer@production.example.invalid + "deploy $image_ref" +) +[[ "$(wc -l <"$tmpdir/ssh-calls")" -eq 1 ]] || fail 'deploy must invoke SSH exactly once' +[[ "${#actual[@]}" -eq "${#expected[@]}" ]] || fail 'SSH argument count mismatch' +for ((i = 0; i < ${#expected[@]}; i++)); do + [[ "${actual[$i]}" == "${expected[$i]}" ]] || fail "SSH argument $i mismatch" done +for invalid in 'ghcr.io/htexplicit/sub2api:latest' "$image_ref runtime=preserve" "$image_ref;id"; do + if run_apply "$invalid"; then fail 'invalid image reference was accepted'; fi + [[ ! -s "$tmpdir/ssh-calls" && ! -s "$tmpdir/ssh-capture" ]] || fail 'rejected reference invoked SSH' +done +MOCK_VPS_PORT=not-a-port +if run_apply "$image_ref"; then fail 'invalid SSH port was accepted'; fi +[[ ! -s "$tmpdir/ssh-calls" && ! -s "$tmpdir/ssh-capture" ]] || fail 'rejected SSH port invoked SSH' +unset MOCK_VPS_PORT -printf 'PASS: production deploy, rollback, digest, and Cindy rollout resolution\n' +printf 'PASS: single production deploy, immutable source binding, and pinned SSH command\n' diff --git a/frontend/src/api/__tests__/downstreamStatus.spec.ts b/frontend/src/api/__tests__/downstreamStatus.spec.ts index 7a00e12b41a3..6da24a3ac3da 100644 --- a/frontend/src/api/__tests__/downstreamStatus.spec.ts +++ b/frontend/src/api/__tests__/downstreamStatus.spec.ts @@ -82,7 +82,7 @@ describe('downstream release status', () => { .mockImplementationOnce(() => response([])) .mockImplementationOnce(() => response({ workflow_runs: run ? [{ id: 1, - display_title: 'Deploy v0.1.185-codexrip.1 (preserve)', + display_title: 'Deploy v0.1.185-codexrip.1', html_url: 'https://production', ...run }] : [] })) From 0b3de98eb00a648a5e36bd76083221ab882b9ba3 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 11:07:48 +0800 Subject: [PATCH 03/21] chore(deploy): drop retired settings from the deploy templates The backend reads neither GATEWAY_IMAGE_STUDIO_ENABLED nor GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED (gateway.account_traffic_telemetry_disabled), and no GATEWAY_CINDY_* variable. Remove them from .env.example, the four Compose files, config.example.yaml and deploy/README.md, and put the Gateway block order and the force_http comment back to upstream v0.2.13. deploy/tests/docker-compose-gateway-env-test.sh is upstream's file again: its Image Studio special case leaves with the variable. Differences from upstream that remain, each read by live code: GATEWAY_OPENAI_CODEX_REQUEST_ZSTD, GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE, SECURITY_ACCOUNT_API_KEY_REVEAL_PASSWORD and the MiSans font origins in the example CSP. The /app/skill-registry mounts with their host path variable are left for the change that removes the directory from the image, and the README section on the production workflow's rollout tuple for the change that removes those inputs from the workflow. Co-Authored-By: Claude Opus 5.5 --- deploy/.env.example | 12 ---------- deploy/README.md | 14 ++++------- deploy/config.example.yaml | 7 ++---- deploy/docker-compose.dev.yml | 23 ++++++++----------- deploy/docker-compose.local.yml | 6 +---- deploy/docker-compose.standalone.yml | 5 +--- deploy/docker-compose.yml | 6 +---- .../tests/docker-compose-gateway-env-test.sh | 1 - 8 files changed, 19 insertions(+), 55 deletions(-) diff --git a/deploy/.env.example b/deploy/.env.example index 456d232a9a2b..5f0194af5545 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -301,11 +301,6 @@ GATEWAY_FORCE_CODEX_CLI=false # # 默认:true GATEWAY_OPENAI_CODEX_REQUEST_ZSTD=true -# 关闭 OpenAI 系网关的账号级流量遥测(只观察:仅 Redis 计数器,不改变调度/准入; -# 由 GET /api/v1/admin/accounts/:id/traffic-telemetry 读取)。 -# -# 默认:false -GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED=false # 对 OpenAI OAuth 账号比较客户端 /responses 请求体与最终出站请求体的语义字段:off | observe | enforce。 # observe 仅按账号限频记录 openai_request_integrity_difference 日志(只含字段名),不拒绝、不改写请求; # 账号 extra.request_integrity_mode 可按账号覆盖。 @@ -372,13 +367,6 @@ GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS=10000 # 全量重建周期(秒) GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS=300 -# ----------------------------------------------------------------------------- -# Image Studio -# ----------------------------------------------------------------------------- -# Deploy-time default of the Image Studio switch until an administrator saves -# the image tool setting. -GATEWAY_IMAGE_STUDIO_ENABLED=false - # ----------------------------------------------------------------------------- # Image Generation Keepalive & Concurrency (Optional) # 图片生成保活与并发隔离配置(可选) diff --git a/deploy/README.md b/deploy/README.md index 1d9560709fc3..1468db992135 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -174,14 +174,11 @@ database recovery period is not treated as a permanent process failure. - `schema_migrations` tracks applied migrations (filename + checksum). - Migrations are forward-only; rollback requires a DB backup restore or a manual compensating SQL script. -### Image Studio default and the retained rollout tuple +### The retained rollout tuple -`GATEWAY_IMAGE_STUDIO_ENABLED` is the deploy-time default of the Image Studio -switch until an administrator saves the image tool setting; unset or `false` -keeps Image Studio off. Cindy accounts are ordinary OpenAI API-key accounts and -the backend no longer reads any `GATEWAY_CINDY_*` variable. The production -workflow below still carries its historical `cindy=` tuple and the Cindy -platform-v1 label check; the backend ignores those values. +Cindy accounts are ordinary OpenAI API-key accounts. The production workflow +below still carries its historical `cindy=` tuple and the Cindy platform-v1 +label check; the backend ignores those values. The protected production workflow exposes the five values as typed boolean inputs. The platform and jobs phase is dispatched with: @@ -277,9 +274,6 @@ their OCI source revisions to match valid `main` ancestors, and requires host rejects it before pulling or mutating state unless the running image is byte-for-byte equal to `from=`. Ordinary deploys remain unable to downgrade. -The backend reads only `GATEWAY_IMAGE_STUDIO_ENABLED`; the former -`GATEWAY_CINDY_IMAGE_STUDIO_ENABLED` fallback was removed. - **Verify `users.allowed_groups` → `user_allowed_groups` backfill** During the incremental GORM→Ent migration, `users.allowed_groups` (legacy `BIGINT[]`) is being replaced by a normalized join table `user_allowed_groups(user_id, group_id)`. diff --git a/deploy/config.example.yaml b/deploy/config.example.yaml index 566d819ca8f8..181a2d9c1970 100644 --- a/deploy/config.example.yaml +++ b/deploy/config.example.yaml @@ -276,10 +276,6 @@ gateway: # compact 等其他请求不压缩。出现兼容问题时置 false 回退为明文 JSON。 # 管理后台「Codex 运行设置」保存过开关后以保存值为准,本项只在未保存时生效。 openai_codex_request_zstd: true - # Observe-only per-account traffic telemetry for the OpenAI-family gateway (Redis counters only; no scheduling/admission change). - # 账号级流量遥测(只观察):仅写 Redis 计数器 account_traffic_observe:{id}:*(24h TTL), - # 由 GET /api/v1/admin/accounts/:id/traffic-telemetry 读取;不改变调度/准入。置 true 关闭。 - account_traffic_telemetry_disabled: false # Compare the client /responses body with the final upstream body for OpenAI OAuth accounts: off | observe | enforce. # 对 OpenAI OAuth 账号比较客户端 /responses 请求体与最终出站请求体的语义字段:off | observe | enforce。 # observe 仅按账号限频记录 openai_request_integrity_difference 日志(只含字段名),不拒绝、不改写请求; @@ -359,7 +355,8 @@ gateway: # 按账号类型细分开关 oauth_enabled: true apikey_enabled: true - # 全局强制 HTTP(紧急回滚开关) + # 全局强制 OpenAI Responses 上游使用 HTTP/SSE,不使用 WebSocket(紧急回滚开关)。 + # 此开关不强制 HTTP/1.1;HTTP/2 由 gateway.openai_http2 单独控制。 force_http: false # 允许在 WSv2 下按策略恢复 store=true(默认 false) allow_store_recovery: false diff --git a/deploy/docker-compose.dev.yml b/deploy/docker-compose.dev.yml index 28746bccabc0..873faf40e34b 100644 --- a/deploy/docker-compose.dev.yml +++ b/deploy/docker-compose.dev.yml @@ -58,20 +58,8 @@ services: - NO_PROXY=${SUB2API_DEV_NO_PROXY:-127.0.0.1,localhost,::1,postgres,redis,sub2api,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,.local} # Gateway values come from Compose .env or the shell. # Fallbacks mirror Sub2API backend defaults so omitted values preserve behavior. - - BATCH_IMAGE_ENABLED=${BATCH_IMAGE_ENABLED:-true} - - BATCH_IMAGE_QUEUE_ENABLED=${BATCH_IMAGE_QUEUE_ENABLED:-true} - - BATCH_IMAGE_VERTEX_ENABLED=${BATCH_IMAGE_VERTEX_ENABLED:-true} - - BATCH_IMAGE_VERTEX_PROJECT_ID=${BATCH_IMAGE_VERTEX_PROJECT_ID:-project-28424c50-8df2-46e2-a27} - - BATCH_IMAGE_VERTEX_LOCATION=${BATCH_IMAGE_VERTEX_LOCATION:-global} - - BATCH_IMAGE_VERTEX_MANAGED_GCS_BUCKET=${BATCH_IMAGE_VERTEX_MANAGED_GCS_BUCKET:-sub2-batch-image-prod-project-28424c50-8df2-46e2-a27} - - BATCH_IMAGE_VERTEX_MANAGED_GCS_PREFIX=${BATCH_IMAGE_VERTEX_MANAGED_GCS_PREFIX:-batch-image/prod/{batch_id}} - - BATCH_IMAGE_VERTEX_INPUT_RETENTION_HOURS=${BATCH_IMAGE_VERTEX_INPUT_RETENTION_HOURS:-24} - - BATCH_IMAGE_VERTEX_OUTPUT_RETENTION_HOURS=${BATCH_IMAGE_VERTEX_OUTPUT_RETENTION_HOURS:-72} - - - GATEWAY_MAX_BODY_SIZE=${GATEWAY_MAX_BODY_SIZE:-268435456} - GATEWAY_FORCE_CODEX_CLI=${GATEWAY_FORCE_CODEX_CLI:-false} - GATEWAY_OPENAI_CODEX_REQUEST_ZSTD=${GATEWAY_OPENAI_CODEX_REQUEST_ZSTD:-true} - - GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED=${GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED:-false} - GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE=${GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE:-off} - GATEWAY_OPENAI_COMPACT_MODEL=${GATEWAY_OPENAI_COMPACT_MODEL:-gpt-5.5} - SUB2API_IMAGES_MAIN_MODEL=${SUB2API_IMAGES_MAIN_MODEL:-gpt-5.6-luna} @@ -85,6 +73,7 @@ services: - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_FAILURE_THRESHOLD=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_FAILURE_THRESHOLD:-2} - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_WINDOW_SECONDS=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_WINDOW_SECONDS:-60} - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_TTL_SECONDS=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_TTL_SECONDS:-600} + - GATEWAY_MAX_BODY_SIZE=${GATEWAY_MAX_BODY_SIZE:-268435456} - GATEWAY_MAX_CONNS_PER_HOST=${GATEWAY_MAX_CONNS_PER_HOST:-1024} - GATEWAY_MAX_IDLE_CONNS=${GATEWAY_MAX_IDLE_CONNS:-2560} - GATEWAY_MAX_IDLE_CONNS_PER_HOST=${GATEWAY_MAX_IDLE_CONNS_PER_HOST:-120} @@ -103,7 +92,6 @@ services: - GATEWAY_SCHEDULING_OUTBOX_LAG_REBUILD_FAILURES=${GATEWAY_SCHEDULING_OUTBOX_LAG_REBUILD_FAILURES:-3} - GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS=${GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS:-10000} - GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS=${GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS:-300} - - GATEWAY_IMAGE_STUDIO_ENABLED=${GATEWAY_IMAGE_STUDIO_ENABLED:-} - GATEWAY_IMAGE_STREAM_DATA_INTERVAL_TIMEOUT=${GATEWAY_IMAGE_STREAM_DATA_INTERVAL_TIMEOUT:-900} - GATEWAY_IMAGE_STREAM_KEEPALIVE_INTERVAL=${GATEWAY_IMAGE_STREAM_KEEPALIVE_INTERVAL:-10} - GATEWAY_IMAGE_NONSTREAM_KEEPALIVE_INTERVAL=${GATEWAY_IMAGE_NONSTREAM_KEEPALIVE_INTERVAL:-0} @@ -112,6 +100,15 @@ services: - GATEWAY_IMAGE_CONCURRENCY_OVERFLOW_MODE=${GATEWAY_IMAGE_CONCURRENCY_OVERFLOW_MODE:-reject} - GATEWAY_IMAGE_CONCURRENCY_WAIT_TIMEOUT_SECONDS=${GATEWAY_IMAGE_CONCURRENCY_WAIT_TIMEOUT_SECONDS:-30} - GATEWAY_IMAGE_CONCURRENCY_MAX_WAITING_REQUESTS=${GATEWAY_IMAGE_CONCURRENCY_MAX_WAITING_REQUESTS:-100} + - BATCH_IMAGE_ENABLED=${BATCH_IMAGE_ENABLED:-true} + - BATCH_IMAGE_QUEUE_ENABLED=${BATCH_IMAGE_QUEUE_ENABLED:-true} + - BATCH_IMAGE_VERTEX_ENABLED=${BATCH_IMAGE_VERTEX_ENABLED:-true} + - BATCH_IMAGE_VERTEX_PROJECT_ID=${BATCH_IMAGE_VERTEX_PROJECT_ID:-project-28424c50-8df2-46e2-a27} + - BATCH_IMAGE_VERTEX_LOCATION=${BATCH_IMAGE_VERTEX_LOCATION:-global} + - BATCH_IMAGE_VERTEX_MANAGED_GCS_BUCKET=${BATCH_IMAGE_VERTEX_MANAGED_GCS_BUCKET:-sub2-batch-image-prod-project-28424c50-8df2-46e2-a27} + - BATCH_IMAGE_VERTEX_MANAGED_GCS_PREFIX=${BATCH_IMAGE_VERTEX_MANAGED_GCS_PREFIX:-batch-image/prod/{batch_id}} + - BATCH_IMAGE_VERTEX_INPUT_RETENTION_HOURS=${BATCH_IMAGE_VERTEX_INPUT_RETENTION_HOURS:-24} + - BATCH_IMAGE_VERTEX_OUTPUT_RETENTION_HOURS=${BATCH_IMAGE_VERTEX_OUTPUT_RETENTION_HOURS:-72} depends_on: postgres: condition: service_healthy diff --git a/deploy/docker-compose.local.yml b/deploy/docker-compose.local.yml index 8e8b5cd858d4..7c61a6c0998f 100644 --- a/deploy/docker-compose.local.yml +++ b/deploy/docker-compose.local.yml @@ -168,12 +168,8 @@ services: # ======================================================================= # Gateway values come from Compose .env or the shell. # Fallbacks mirror Sub2API backend defaults so omitted values preserve behavior. - - - - GATEWAY_MAX_BODY_SIZE=${GATEWAY_MAX_BODY_SIZE:-268435456} - GATEWAY_FORCE_CODEX_CLI=${GATEWAY_FORCE_CODEX_CLI:-false} - GATEWAY_OPENAI_CODEX_REQUEST_ZSTD=${GATEWAY_OPENAI_CODEX_REQUEST_ZSTD:-true} - - GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED=${GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED:-false} - GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE=${GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE:-off} - GATEWAY_OPENAI_COMPACT_MODEL=${GATEWAY_OPENAI_COMPACT_MODEL:-gpt-5.5} - SUB2API_IMAGES_MAIN_MODEL=${SUB2API_IMAGES_MAIN_MODEL:-gpt-5.6-luna} @@ -187,6 +183,7 @@ services: - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_FAILURE_THRESHOLD=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_FAILURE_THRESHOLD:-2} - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_WINDOW_SECONDS=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_WINDOW_SECONDS:-60} - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_TTL_SECONDS=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_TTL_SECONDS:-600} + - GATEWAY_MAX_BODY_SIZE=${GATEWAY_MAX_BODY_SIZE:-268435456} - GATEWAY_MAX_CONNS_PER_HOST=${GATEWAY_MAX_CONNS_PER_HOST:-1024} - GATEWAY_MAX_IDLE_CONNS=${GATEWAY_MAX_IDLE_CONNS:-2560} - GATEWAY_MAX_IDLE_CONNS_PER_HOST=${GATEWAY_MAX_IDLE_CONNS_PER_HOST:-120} @@ -205,7 +202,6 @@ services: - GATEWAY_SCHEDULING_OUTBOX_LAG_REBUILD_FAILURES=${GATEWAY_SCHEDULING_OUTBOX_LAG_REBUILD_FAILURES:-3} - GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS=${GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS:-10000} - GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS=${GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS:-300} - - GATEWAY_IMAGE_STUDIO_ENABLED=${GATEWAY_IMAGE_STUDIO_ENABLED:-} - GATEWAY_IMAGE_STREAM_DATA_INTERVAL_TIMEOUT=${GATEWAY_IMAGE_STREAM_DATA_INTERVAL_TIMEOUT:-900} - GATEWAY_IMAGE_STREAM_KEEPALIVE_INTERVAL=${GATEWAY_IMAGE_STREAM_KEEPALIVE_INTERVAL:-10} - GATEWAY_IMAGE_NONSTREAM_KEEPALIVE_INTERVAL=${GATEWAY_IMAGE_NONSTREAM_KEEPALIVE_INTERVAL:-0} diff --git a/deploy/docker-compose.standalone.yml b/deploy/docker-compose.standalone.yml index 5d29b087fb83..e20900e55d7b 100644 --- a/deploy/docker-compose.standalone.yml +++ b/deploy/docker-compose.standalone.yml @@ -113,11 +113,8 @@ services: # ======================================================================= # Gateway values come from Compose .env or the shell. # Fallbacks mirror Sub2API backend defaults so omitted values preserve behavior. - - - GATEWAY_MAX_BODY_SIZE=${GATEWAY_MAX_BODY_SIZE:-268435456} - GATEWAY_FORCE_CODEX_CLI=${GATEWAY_FORCE_CODEX_CLI:-false} - GATEWAY_OPENAI_CODEX_REQUEST_ZSTD=${GATEWAY_OPENAI_CODEX_REQUEST_ZSTD:-true} - - GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED=${GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED:-false} - GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE=${GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE:-off} - GATEWAY_OPENAI_COMPACT_MODEL=${GATEWAY_OPENAI_COMPACT_MODEL:-gpt-5.5} - SUB2API_IMAGES_MAIN_MODEL=${SUB2API_IMAGES_MAIN_MODEL:-gpt-5.6-luna} @@ -131,6 +128,7 @@ services: - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_FAILURE_THRESHOLD=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_FAILURE_THRESHOLD:-2} - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_WINDOW_SECONDS=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_WINDOW_SECONDS:-60} - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_TTL_SECONDS=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_TTL_SECONDS:-600} + - GATEWAY_MAX_BODY_SIZE=${GATEWAY_MAX_BODY_SIZE:-268435456} - GATEWAY_MAX_CONNS_PER_HOST=${GATEWAY_MAX_CONNS_PER_HOST:-1024} - GATEWAY_MAX_IDLE_CONNS=${GATEWAY_MAX_IDLE_CONNS:-2560} - GATEWAY_MAX_IDLE_CONNS_PER_HOST=${GATEWAY_MAX_IDLE_CONNS_PER_HOST:-120} @@ -149,7 +147,6 @@ services: - GATEWAY_SCHEDULING_OUTBOX_LAG_REBUILD_FAILURES=${GATEWAY_SCHEDULING_OUTBOX_LAG_REBUILD_FAILURES:-3} - GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS=${GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS:-10000} - GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS=${GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS:-300} - - GATEWAY_IMAGE_STUDIO_ENABLED=${GATEWAY_IMAGE_STUDIO_ENABLED:-} - GATEWAY_IMAGE_STREAM_DATA_INTERVAL_TIMEOUT=${GATEWAY_IMAGE_STREAM_DATA_INTERVAL_TIMEOUT:-900} - GATEWAY_IMAGE_STREAM_KEEPALIVE_INTERVAL=${GATEWAY_IMAGE_STREAM_KEEPALIVE_INTERVAL:-10} - GATEWAY_IMAGE_NONSTREAM_KEEPALIVE_INTERVAL=${GATEWAY_IMAGE_NONSTREAM_KEEPALIVE_INTERVAL:-0} diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 56804facb9f6..6eecba5ab1bd 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -167,12 +167,8 @@ services: # ======================================================================= # Gateway values come from Compose .env or the shell. # Fallbacks mirror Sub2API backend defaults so omitted values preserve behavior. - - - - GATEWAY_MAX_BODY_SIZE=${GATEWAY_MAX_BODY_SIZE:-268435456} - GATEWAY_FORCE_CODEX_CLI=${GATEWAY_FORCE_CODEX_CLI:-false} - GATEWAY_OPENAI_CODEX_REQUEST_ZSTD=${GATEWAY_OPENAI_CODEX_REQUEST_ZSTD:-true} - - GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED=${GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED:-false} - GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE=${GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE:-off} - GATEWAY_OPENAI_COMPACT_MODEL=${GATEWAY_OPENAI_COMPACT_MODEL:-gpt-5.5} - SUB2API_IMAGES_MAIN_MODEL=${SUB2API_IMAGES_MAIN_MODEL:-gpt-5.6-luna} @@ -186,6 +182,7 @@ services: - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_FAILURE_THRESHOLD=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_FAILURE_THRESHOLD:-2} - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_WINDOW_SECONDS=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_WINDOW_SECONDS:-60} - GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_TTL_SECONDS=${GATEWAY_OPENAI_PROXY_STREAM_CIRCUIT_TTL_SECONDS:-600} + - GATEWAY_MAX_BODY_SIZE=${GATEWAY_MAX_BODY_SIZE:-268435456} - GATEWAY_MAX_CONNS_PER_HOST=${GATEWAY_MAX_CONNS_PER_HOST:-1024} - GATEWAY_MAX_IDLE_CONNS=${GATEWAY_MAX_IDLE_CONNS:-2560} - GATEWAY_MAX_IDLE_CONNS_PER_HOST=${GATEWAY_MAX_IDLE_CONNS_PER_HOST:-120} @@ -204,7 +201,6 @@ services: - GATEWAY_SCHEDULING_OUTBOX_LAG_REBUILD_FAILURES=${GATEWAY_SCHEDULING_OUTBOX_LAG_REBUILD_FAILURES:-3} - GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS=${GATEWAY_SCHEDULING_OUTBOX_BACKLOG_REBUILD_ROWS:-10000} - GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS=${GATEWAY_SCHEDULING_FULL_REBUILD_INTERVAL_SECONDS:-300} - - GATEWAY_IMAGE_STUDIO_ENABLED=${GATEWAY_IMAGE_STUDIO_ENABLED:-} - GATEWAY_IMAGE_STREAM_DATA_INTERVAL_TIMEOUT=${GATEWAY_IMAGE_STREAM_DATA_INTERVAL_TIMEOUT:-900} - GATEWAY_IMAGE_STREAM_KEEPALIVE_INTERVAL=${GATEWAY_IMAGE_STREAM_KEEPALIVE_INTERVAL:-10} - GATEWAY_IMAGE_NONSTREAM_KEEPALIVE_INTERVAL=${GATEWAY_IMAGE_NONSTREAM_KEEPALIVE_INTERVAL:-0} diff --git a/deploy/tests/docker-compose-gateway-env-test.sh b/deploy/tests/docker-compose-gateway-env-test.sh index 07c88dd1ee91..f068410ba2eb 100644 --- a/deploy/tests/docker-compose-gateway-env-test.sh +++ b/deploy/tests/docker-compose-gateway-env-test.sh @@ -32,7 +32,6 @@ do GATEWAY_MAX_CONNS_PER_HOST) value=1024 ;; GATEWAY_MAX_IDLE_CONNS) value=2560 ;; GATEWAY_MAX_IDLE_CONNS_PER_HOST) value=120 ;; - GATEWAY_IMAGE_STUDIO_ENABLED) value= ;; esac expected=$(printf ' - %s=${%s:-%s}' "$key" "$key" "$value") From 9b860495e81d17eb4005dd4e8b3af197e20c88a6 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 11:08:13 +0800 Subject: [PATCH 04/21] ci(release): remove what the signed plugin bundle left in the release tooling release_preflight.py: --kind accepted one value and local_assets always returned nothing, so the per-asset comparison never ran. Both go, with the root argument and ROOT that only they used. The four stages check what they checked before; a draft that carries assets now fails with draft_assets_unexpected instead of draft_assets_incomplete. The command line is now release_preflight.py --stage \ --tag --source-sha [--image-digest ] and the four calls in downstream-release.yml use it. downstream-release.yml: drop the pnpm, Node and Go setup steps. The image is built inside Docker and no later step runs those tools. Image labels are unchanged. test_release_preflight.py: the assertions naming plugin-era artifacts go; the provenance and Image:/Source: assertions they shared a test with move into the remaining workflow contract. A new contract passes every preflight invocation in the workflow through the script's argument parser, which a pull request could not exercise before. deploy/plugin-bundle/README.md described the bundle's build input. Co-Authored-By: Claude Opus 5.5 --- .github/scripts/release_preflight.py | 43 +++------ .github/scripts/test_release_preflight.py | 106 ++++++++++++---------- .github/workflows/downstream-release.yml | 20 +--- deploy/plugin-bundle/README.md | 5 - 4 files changed, 75 insertions(+), 99 deletions(-) delete mode 100644 deploy/plugin-bundle/README.md diff --git a/.github/scripts/release_preflight.py b/.github/scripts/release_preflight.py index 848dc4f23a1f..6e5c89e3cc51 100644 --- a/.github/scripts/release_preflight.py +++ b/.github/scripts/release_preflight.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Fixed read-only GitHub/GHCR publication checks; never signs or publishes.""" +"""Fixed read-only GitHub/GHCR publication checks; never publishes.""" from __future__ import annotations @@ -8,7 +8,6 @@ import hashlib import json import os -from pathlib import Path import re import subprocess import sys @@ -17,10 +16,9 @@ import urllib.request -ROOT = Path(__file__).resolve().parents[2] REPOSITORY = "HTExplicit/sub2api" IMAGE = "ghcr.io/htexplicit/sub2api" -HOST_TAG = re.compile(r"v[0-9]+\.[0-9]+\.[0-9]+-codexrip\.[1-9][0-9]*") +RELEASE_TAG = re.compile(r"v[0-9]+\.[0-9]+\.[0-9]+-codexrip\.[1-9][0-9]*") SHA = re.compile(r"[a-f0-9]{40}") DIGEST = re.compile(r"sha256:[a-f0-9]{64}") MAX_PAGES = 100 @@ -107,7 +105,7 @@ def http_get(url: str, headers: dict[str, str]): def registry_manifest(version: str, request=http_get, token=None, actor=None): - require(HOST_TAG.fullmatch("v" + version) is not None, "image_version_invalid") + require(RELEASE_TAG.fullmatch("v" + version) is not None, "image_version_invalid") token = token if token is not None else os.environ.get("GH_TOKEN", "") actor = actor if actor is not None else os.environ.get("GITHUB_ACTOR", "") require(bool(token) and bool(actor), "registry_auth_unavailable") @@ -140,16 +138,9 @@ def registry_manifest(version: str, request=http_get, token=None, actor=None): return digest -def local_assets(args, root: Path) -> dict[str, tuple[int, str]]: - # Native domains ship in the immutable OCI image; there are no separate - # first-party package assets attached to a host release. - return {} - - -def check(args, github=github_json, registry=registry_manifest, root=ROOT): +def check(args, github=github_json, registry=registry_manifest): require(SHA.fullmatch(args.source_sha) is not None, "source_sha_invalid") - require(args.kind == "host", "release_kind_invalid") - require(HOST_TAG.fullmatch(args.tag) is not None, "release_tag_invalid") + require(RELEASE_TAG.fullmatch(args.tag) is not None, "release_tag_invalid") releases = list_releases(github) matches = [release for release in releases if release["tag_name"] == args.tag] if args.stage == "before-publish": @@ -160,25 +151,16 @@ def check(args, github=github_json, registry=registry_manifest, root=ROOT): # GitHub may retain a branch name for an existing tag; only the tag's # dereferenced commit below is authoritative. A supplied SHA must agree. require(SHA.fullmatch(target) is None or target == args.source_sha, "draft_target_mismatch") - expected = local_assets(args, root) + # The image is the whole release; its draft carries no assets. assets = release.get("assets") - require(isinstance(assets, list) and len(assets) == len(expected), "draft_assets_incomplete") - seen = set() - for asset in assets: - require(isinstance(asset, dict) and asset.get("name") in expected - and asset["name"] not in seen and asset.get("state") == "uploaded", "draft_assets_incomplete") - seen.add(asset["name"]) - size, digest = expected[asset["name"]] - require(type(asset.get("size")) is int and asset["size"] == size - and asset.get("digest") == digest, "draft_asset_digest_mismatch") + require(isinstance(assets, list) and not assets, "draft_assets_unexpected") else: require(not matches, "release_already_exists") - if args.kind == "host": - digest = registry(args.tag[1:]) - if args.stage in ("before-build", "before-push"): - require(digest is None, "version_image_already_exists") - else: - require(DIGEST.fullmatch(args.image_digest) is not None and digest == args.image_digest, "published_image_digest_mismatch") + digest = registry(args.tag[1:]) + if args.stage in ("before-build", "before-push"): + require(digest is None, "version_image_already_exists") + else: + require(DIGEST.fullmatch(args.image_digest) is not None and digest == args.image_digest, "published_image_digest_mismatch") # These are deliberately the final remote reads before the workflow's next # write. They reduce the gap, but cannot replace server-side immutable tags. require(tag_commit(github, args.tag) == args.source_sha, "release_tag_changed") @@ -190,7 +172,6 @@ def check(args, github=github_json, registry=registry_manifest, root=ROOT): def main(argv=None) -> int: parser = argparse.ArgumentParser() - parser.add_argument("--kind", choices=("host",), required=True) parser.add_argument("--stage", choices=("before-build", "before-push", "before-create", "before-publish"), required=True) parser.add_argument("--tag", required=True) parser.add_argument("--source-sha", required=True) diff --git a/.github/scripts/test_release_preflight.py b/.github/scripts/test_release_preflight.py index 5aaf2f638a08..019d526912d4 100644 --- a/.github/scripts/test_release_preflight.py +++ b/.github/scripts/test_release_preflight.py @@ -2,12 +2,15 @@ """Only publication metadata mocks and workflow contracts; no external writes.""" import argparse +import contextlib import copy import hashlib +import io import json import os from pathlib import Path import re +import shlex import shutil import subprocess import tempfile @@ -18,13 +21,14 @@ import release_preflight as guard +WORKFLOW = Path(__file__).resolve().parents[2] / ".github/workflows/downstream-release.yml" SOURCE = "a" * 40 TAG = "v0.2.7-codexrip.1" IMAGE_DIGEST = "sha256:" + "c" * 64 -def options(stage="before-push", kind="host"): - return argparse.Namespace(kind=kind, stage=stage, tag=TAG, source_sha=SOURCE, +def options(stage="before-push"): + return argparse.Namespace(stage=stage, tag=TAG, source_sha=SOURCE, image_digest=IMAGE_DIGEST if stage in ("before-create", "before-publish") else "") @@ -123,31 +127,35 @@ def test_existing_image_and_later_digest_drift_are_rejected(self): with self.subTest(observed=observed), self.assertRaisesRegex(guard.PreflightError, "published_image_digest_mismatch"): guard.check(args, github=Repository(args), registry=lambda _: observed) - def test_complete_draft_assets_and_source_allow_publication_by_id(self): + def test_asset_free_draft_and_source_allow_publication_by_id(self): for target in (SOURCE, "main"): - with self.subTest(target=target), tempfile.TemporaryDirectory() as tmp: + with self.subTest(target=target): args = options("before-publish") release = {"id": 101, "tag_name": args.tag, "draft": True, "target_commitish": target, "assets": []} repo = Repository(args, {1: [release]}) - result = guard.check(args, github=repo, registry=lambda _: IMAGE_DIGEST, root=Path(tmp)) + result = guard.check(args, github=repo, registry=lambda _: IMAGE_DIGEST) self.assertEqual(101, result["release_id"]) self.assertEqual("git/ref/tags/" + args.tag, repo.calls[-1]) - def test_missing_or_changed_draft_asset_metadata_prevents_publication(self): - for mutation in ("unexpected-package", "invalid-assets", "wrong-target"): - with self.subTest(mutation=mutation), tempfile.TemporaryDirectory() as tmp: + def test_draft_assets_or_another_target_prevent_publication(self): + for mutation, code in ( + ("unexpected-asset", "draft_assets_unexpected"), + ("invalid-assets", "draft_assets_unexpected"), + ("wrong-target", "draft_target_mismatch"), + ): + with self.subTest(mutation=mutation): args = options("before-publish") release = {"id": 101, "tag_name": TAG, "draft": True, "target_commitish": SOURCE, "assets": []} - if mutation == "unexpected-package": - release["assets"] = [{"name": "old.s2plugin", "state": "uploaded"}] + if mutation == "unexpected-asset": + release["assets"] = [{"name": "unexpected.tar.gz", "state": "uploaded"}] if mutation == "invalid-assets": release["assets"] = None if mutation == "wrong-target": release["target_commitish"] = "d" * 40 - with self.assertRaises(guard.PreflightError): - guard.check(args, github=Repository(args, {1: [release]}), registry=lambda _: IMAGE_DIGEST, root=Path(tmp)) + with self.assertRaisesRegex(guard.PreflightError, code): + guard.check(args, github=Repository(args, {1: [release]}), registry=lambda _: IMAGE_DIGEST) class ReleaseWorkflowContracts(unittest.TestCase): @@ -160,11 +168,10 @@ def test_git_authentication_is_temporary_and_only_fetches_main(self): bash = shutil.which("bash") if bash is None: self.skipTest("Bash is required for the environment-only fixture") - for name in ("downstream-release.yml",): - source = (guard.ROOT / ".github/workflows" / name).read_text(encoding="utf-8") - snippet = re.search(r"(?ms)^ authorization=\$\(.*?^ unset authorization$", source) - self.assertIsNotNone(snippet) - body = r''' + source = WORKFLOW.read_text(encoding="utf-8") + snippet = re.search(r"(?ms)^ authorization=\$\(.*?^ unset authorization$", source) + self.assertIsNotNone(snippet) + body = r''' set -euo pipefail GH_TOKEN=fixture-job-token calls=0 @@ -181,50 +188,55 @@ def test_git_authentication_is_temporary_and_only_fetches_main(self): [[ "$calls" == 1 && -z ${authorization+x} && -z ${GIT_CONFIG_COUNT+x} && -z ${GIT_CONFIG_VALUE_0+x} ]] printf 'TEMPORARY_GIT_AUTH|state=passed|real_git=false\n' ''' - with self.subTest(workflow=name), tempfile.TemporaryDirectory() as tmp: - result = subprocess.run([bash, "-c", body], cwd=tmp, capture_output=True, text=True, timeout=15) - self.assertEqual(0, result.returncode) - self.assertIn("TEMPORARY_GIT_AUTH|state=passed", result.stdout) - self.assertNotIn("fixture-job-token", result.stdout + result.stderr) + with tempfile.TemporaryDirectory() as tmp: + result = subprocess.run([bash, "-c", body], cwd=tmp, capture_output=True, text=True, timeout=15) + self.assertEqual(0, result.returncode) + self.assertIn("TEMPORARY_GIT_AUTH|state=passed", result.stdout) + self.assertNotIn("fixture-job-token", result.stdout + result.stderr) def test_write_credentials_are_not_in_build_environments(self): - for name in ("downstream-release.yml",): - source = (guard.ROOT / ".github/workflows" / name).read_text(encoding="utf-8") - self.assertEqual([], re.findall(r"(?m)^ GH_TOKEN:.*$", source), "a job-wide token reaches dependency/build subprocesses") - self.assertEqual(source.count("uses: actions/checkout@"), source.count("persist-credentials: false")) - self.assertIn("GIT_CONFIG_COUNT=1", source) - self.assertIn("GIT_CONFIG_VALUE_0=", source) - self.assertNotIn("git config --global", source) - self.assertNotIn("git config --local", source) - for step in source.split(" - "): - if "pnpm --dir frontend install" in step or "go build" in step or "uses: docker/build-push-action@" in step: - self.assertNotIn("GH_TOKEN:", step) - host = (guard.ROOT / ".github/workflows/downstream-release.yml").read_text(encoding="utf-8") - self.assertLess(host.index("name: Build release image"), host.index("uses: docker/login-action@")) - self.assertLess(host.index("uses: docker/login-action@"), host.index('docker push "$IMAGE:$VERSION"')) - - def test_host_uses_admitted_sha_and_builds_before_guarded_push(self): - source = (guard.ROOT / ".github/workflows/downstream-release.yml").read_text(encoding="utf-8") + source = WORKFLOW.read_text(encoding="utf-8") + self.assertEqual([], re.findall(r"(?m)^ GH_TOKEN:.*$", source), "a job-wide token reaches dependency/build subprocesses") + self.assertEqual(source.count("uses: actions/checkout@"), source.count("persist-credentials: false")) + self.assertIn("GIT_CONFIG_COUNT=1", source) + self.assertIn("GIT_CONFIG_VALUE_0=", source) + self.assertNotIn("git config --global", source) + self.assertNotIn("git config --local", source) + for step in source.split(" - "): + if "uses: docker/build-push-action@" in step: + self.assertNotIn("GH_TOKEN:", step) + self.assertLess(source.index("name: Build release image"), source.index("uses: docker/login-action@")) + self.assertLess(source.index("uses: docker/login-action@"), source.index('docker push "$IMAGE:$VERSION"')) + + def test_release_uses_admitted_sha_and_builds_before_guarded_push(self): + source = WORKFLOW.read_text(encoding="utf-8") self.assertIn("ref: refs/tags/${{ env.RELEASE_TAG }}", source) self.assertIn("ref: ${{ needs.verify.outputs.source_sha }}", source) self.assertIn("load: true", source) self.assertIn("push: false", source) self.assertLess(source.index("--stage before-push"), source.index('docker push "$IMAGE:$VERSION"')) + self.assertIn("Attest image provenance", source) self.assertIn("--draft", source) self.assertIn('--target "$SOURCE_SHA"', source) + self.assertIn("Image:", source) + self.assertIn("Source:", source) self.assertIn("--stage before-publish", source) self.assertIn('releases/$RELEASE_ID', source) self.assertNotIn("--clobber", source) self.assertNotIn("gh release delete", source) - def test_native_release_has_no_first_party_signing_or_upload(self): - source = (guard.ROOT / ".github/workflows/downstream-release.yml").read_text(encoding="utf-8") - for retired in ("SUB2API_PLUGIN_SIGNING_KEY", "package-plugin", "plugin-bundle", ".s2plugin", "extensionapi/ui"): - self.assertNotIn(retired, source) - self.assertIn("Attest image provenance", source) - self.assertIn("Image:", source) - self.assertIn("Source:", source) - self.assertFalse((guard.ROOT / ".github/workflows/plugin-release.yml").exists()) + def test_every_workflow_invocation_is_a_valid_preflight_command_line(self): + source = WORKFLOW.read_text(encoding="utf-8") + stages = [] + for command in re.findall(r"release_preflight\.py((?:\\\n|[^\n)])*)", source): + with mock.patch.object(guard, "check", return_value={"state": "verified"}) as check, \ + mock.patch.dict(os.environ, {"GITHUB_REPOSITORY": guard.REPOSITORY, "GH_TOKEN": "fixture-token"}), \ + contextlib.redirect_stdout(io.StringIO()): + self.assertEqual(0, guard.main(shlex.split(command.replace("\\\n", " ")))) + args = check.call_args.args[0] + self.assertEqual(args.stage in ("before-create", "before-publish"), bool(args.image_digest)) + stages.append(args.stage) + self.assertEqual(["before-build", "before-push", "before-create", "before-publish"], stages) if __name__ == "__main__": diff --git a/.github/workflows/downstream-release.yml b/.github/workflows/downstream-release.yml index 6b24c551edad..f7fa84a56f92 100644 --- a/.github/workflows/downstream-release.yml +++ b/.github/workflows/downstream-release.yml @@ -91,20 +91,8 @@ jobs: run: | set -euo pipefail [[ "$(git rev-parse HEAD)" == "$SOURCE_SHA" ]] - python3 .github/scripts/release_preflight.py --kind host --stage before-build \ + python3 .github/scripts/release_preflight.py --stage before-build \ --tag "$RELEASE_TAG" --source-sha "$SOURCE_SHA" - - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6 - with: - version: 9.15.9 - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 - with: - node-version: '20' - cache: pnpm - cache-dependency-path: frontend/pnpm-lock.yaml - - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 - with: - go-version-file: backend/go.mod - cache-dependency-path: backend/go.sum - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - name: Build release image without publication id: build @@ -146,7 +134,7 @@ jobs: run: | set -euo pipefail [[ "$(git rev-parse HEAD)" == "$SOURCE_SHA" ]] - python3 .github/scripts/release_preflight.py --kind host --stage before-push \ + python3 .github/scripts/release_preflight.py --stage before-push \ --tag "$RELEASE_TAG" --source-sha "$SOURCE_SHA" docker push "$IMAGE:$VERSION" image_ref=$(docker image inspect --format '{{json .RepoDigests}}' "$IMAGE:$VERSION" | \ @@ -173,7 +161,7 @@ jobs: Image: \`${IMAGE}:${VERSION}@${IMAGE_DIGEST}\` Source: \`${SOURCE_SHA}\` EOF - python3 .github/scripts/release_preflight.py --kind host --stage before-create \ + python3 .github/scripts/release_preflight.py --stage before-create \ --tag "$RELEASE_TAG" --source-sha "$SOURCE_SHA" --image-digest "$IMAGE_DIGEST" gh release create "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \ --verify-tag --draft --target "$SOURCE_SHA" \ @@ -187,7 +175,7 @@ jobs: run: | set -euo pipefail [[ "$(git rev-parse HEAD)" == "$SOURCE_SHA" ]] - result=$(python3 .github/scripts/release_preflight.py --kind host --stage before-publish \ + result=$(python3 .github/scripts/release_preflight.py --stage before-publish \ --tag "$RELEASE_TAG" --source-sha "$SOURCE_SHA" --image-digest "$IMAGE_DIGEST") RELEASE_ID=$(jq -er '.release_id | select(type == "number" and . > 0)' <<< "$result") [[ "$RELEASE_ID" =~ ^[1-9][0-9]*$ ]] diff --git a/deploy/plugin-bundle/README.md b/deploy/plugin-bundle/README.md deleted file mode 100644 index 00985279220a..000000000000 --- a/deploy/plugin-bundle/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# 正式插件制品输入 - -正式发布工作流在 `current/` 生成签名 `.s2plugin` 包和 `lock.json`。镜像选择 `PLUGIN_BUNDLE_STAGE=plugin-bundle-release`,校验后原样复制这些制品;此目录不保存私钥。 - -`current/` 是构建输出,不提交源码。默认本地和候选镜像使用独立的开发签名阶段,正式 Codexrip 版本不能加载开发发布者签名的集合。 From d9780bec8e9cc2e50174e34e885e622a2dd7d05d Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 11:08:44 +0800 Subject: [PATCH 05/21] ci(upstream-risk): stop guarding paths that exist neither here nor upstream plugins/ and backend/pkg/extensionapi/ were first-party plugin directories; upstream has neither and ignores a top-level plugins/. Upstream's own plugin framework stays critical through backend/pkg/pluginapi/ and service/plugin_*. The test names files that exist: plugin_manager.go replaces a first-party file deleted in September, and the two samples under the removed directories go. Co-Authored-By: Claude Opus 5.5 --- .github/scripts/test_upstream_risk.py | 4 +--- .github/scripts/upstream_risk.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/scripts/test_upstream_risk.py b/.github/scripts/test_upstream_risk.py index 45fe17185689..b6759e5f06dd 100644 --- a/.github/scripts/test_upstream_risk.py +++ b/.github/scripts/test_upstream_risk.py @@ -33,10 +33,8 @@ def test_every_guarded_family_is_critical(self): "backend/internal/securityaudit/policy.go", "backend/internal/service/billing_service.go", "backend/internal/service/openai_ws_pool.go", - "backend/internal/service/plugin_update.go", - "backend/pkg/extensionapi/v1/rpc.go", + "backend/internal/service/plugin_manager.go", "backend/pkg/pluginapi/v1/plugin.proto", - "plugins/codex-runtime/manifest.source.json", ): with self.subTest(path=path): self.assertTrue(is_critical(path)) diff --git a/.github/scripts/upstream_risk.py b/.github/scripts/upstream_risk.py index 74e580fb78cf..45fbba77ee19 100644 --- a/.github/scripts/upstream_risk.py +++ b/.github/scripts/upstream_risk.py @@ -15,7 +15,7 @@ re.compile(r"^(?:Dockerfile|docker-compose[^/]*\.ya?ml|deploy/|\.dockerignore$)"), re.compile(r"^(?:backend/go\.(?:mod|sum)|frontend/(?:package\.json|pnpm-lock\.yaml))$"), re.compile(r"^backend/(?:migrations|ent)/"), - re.compile(r"^(?:plugins/|backend/pkg/(?:pluginapi|extensionapi)/)"), + re.compile(r"^backend/pkg/pluginapi/"), re.compile( r"^backend/internal/(?:auth|securityaudit|repository|server/middleware|service/" r"(?:billing|pricing|ratelimit|account_scheduler|gateway|openai_|plugin_|api_key_auth))" From 98c957a0ed8c050219fe48ccdd5801d3293f64d8 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 11:08:47 +0800 Subject: [PATCH 06/21] ci: delete the one-off legacy GHCR cleanup workflow It deleted the 0.1.172-codexrip.3 to .9 package versions on 2026-08-11. It requires each of those versions to exist before it deletes anything, so a second run can only fail. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/legacy-ghcr-cleanup.yml | 149 ---------------------- 1 file changed, 149 deletions(-) delete mode 100644 .github/workflows/legacy-ghcr-cleanup.yml diff --git a/.github/workflows/legacy-ghcr-cleanup.yml b/.github/workflows/legacy-ghcr-cleanup.yml deleted file mode 100644 index 6e66a2327085..000000000000 --- a/.github/workflows/legacy-ghcr-cleanup.yml +++ /dev/null @@ -1,149 +0,0 @@ -name: Legacy GHCR Cleanup - -on: - workflow_dispatch: - inputs: - confirmation: - description: 'Type DELETE_LEGACY_GHCR to remove the retired .3-.9 package versions' - required: true - type: string - -permissions: - contents: read - packages: write - -concurrency: - group: legacy-ghcr-cleanup - cancel-in-progress: false - -jobs: - delete-retired-versions: - if: ${{ github.ref == 'refs/heads/main' && inputs.confirmation == 'DELETE_LEGACY_GHCR' }} - runs-on: ubuntu-latest - timeout-minutes: 10 - env: - GH_TOKEN: ${{ github.token }} - PACKAGE_API: https://api.github.com/users/HTExplicit/packages/container/sub2api/versions - steps: - - name: Validate and delete retired package versions - shell: bash - run: | - set -euo pipefail - - target_tags=( - 0.1.172-codexrip.3 - 0.1.172-codexrip.4 - 0.1.172-codexrip.5 - 0.1.172-codexrip.6 - 0.1.172-codexrip.7 - 0.1.172-codexrip.8 - 0.1.172-codexrip.9 - ) - protected_tags=( - 0.1.172-codexrip.10 - 0.1.172-codexrip.11 - 0.1.172-codexrip.12 - ) - - fetch_versions() { - local pages - pages="$(gh api --paginate --slurp "${PACKAGE_API}?per_page=100")" - jq -c 'add // []' <<<"$pages" - } - - find_tag_versions() { - local versions=$1 - local tag=$2 - jq -c --arg tag "$tag" \ - '[.[] | select(((.metadata.container.tags // []) | index($tag)) != null)]' \ - <<<"$versions" - } - - require_single_tag_version() { - local versions=$1 - local tag=$2 - local matches count tags_json expected_tags id digest - matches="$(find_tag_versions "$versions" "$tag")" - count="$(jq 'length' <<<"$matches")" - if [[ "$count" != 1 ]]; then - echo "expected exactly one package version for tag $tag; found $count" >&2 - return 1 - fi - tags_json="$(jq -c '.[0].metadata.container.tags // [] | sort' <<<"$matches")" - expected_tags="$(jq -cn --arg tag "$tag" '[$tag]')" - if [[ "$tags_json" != "$expected_tags" ]]; then - echo "refusing a multi-tag package version for $tag: $tags_json" >&2 - return 1 - fi - id="$(jq -r '.[0].id | tostring' <<<"$matches")" - digest="$(jq -r '.[0].name // empty' <<<"$matches")" - if [[ ! "$id" =~ ^[0-9]+$ || -z "$digest" ]]; then - echo "package version for $tag has no stable ID/digest" >&2 - return 1 - fi - printf '%s\t%s\t%s\n' "$tag" "$id" "$digest" - } - - if [[ "$GITHUB_REF" != refs/heads/main ]]; then - echo 'cleanup must run from main' >&2 - exit 1 - fi - - versions_before="$(fetch_versions)" - declare -A protected_ids=() - declare -A protected_digests=() - declare -A protected_rows=() - for tag in "${protected_tags[@]}"; do - row="$(require_single_tag_version "$versions_before" "$tag")" - IFS=$'\t' read -r row_tag row_id row_digest <<<"$row" - protected_ids["$row_id"]="$row_tag" - protected_digests["$row_digest"]="$row_tag" - protected_rows["$row_tag"]="$row_id|$row_digest" - echo "protected tag=$row_tag version_id=$row_id digest=$row_digest" - done - - declare -A target_ids=() - target_count=0 - for tag in "${target_tags[@]}"; do - row="$(require_single_tag_version "$versions_before" "$tag")" - IFS=$'\t' read -r row_tag row_id row_digest <<<"$row" - if [[ -n "${protected_ids[$row_id]+set}" || -n "${protected_digests[$row_digest]+set}" ]]; then - echo "refusing to delete protected version for $row_tag" >&2 - exit 1 - fi - target_ids["$row_tag"]="$row_id" - target_count=$((target_count + 1)) - echo "validated target tag=$row_tag version_id=$row_id digest=$row_digest" - done - if [[ "$target_count" != 7 ]]; then - echo "expected seven retired package versions; found $target_count" >&2 - exit 1 - fi - - for tag in "${target_tags[@]}"; do - version_id="${target_ids[$tag]}" - gh api --method DELETE "${PACKAGE_API}/${version_id}" >/dev/null - echo "deleted tag=$tag version_id=$version_id" - done - - versions_after="$(fetch_versions)" - for tag in "${target_tags[@]}"; do - count="$(jq -r --arg tag "$tag" '[.[] | select(((.metadata.container.tags // []) | index($tag)) != null)] | length' <<<"$versions_after")" - if [[ "$count" != 0 ]]; then - echo "retired tag still exists after deletion: $tag" >&2 - exit 1 - fi - done - - for tag in "${protected_tags[@]}"; do - row="$(require_single_tag_version "$versions_after" "$tag")" - IFS=$'\t' read -r row_tag row_id row_digest <<<"$row" - expected="${protected_rows[$row_tag]}" - if [[ "$row_id|$row_digest" != "$expected" ]]; then - echo "protected version changed for $row_tag" >&2 - exit 1 - fi - echo "protected unchanged tag=$row_tag version_id=$row_id digest=$row_digest" - done - - echo "GHCR_LEGACY_CLEANUP_OK deleted=7 protected=3" From 0bc6c94a49e43915d682b01013deca3b2d35b6c2 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 11:08:49 +0800 Subject: [PATCH 07/21] docs: bring DOWNSTREAM.md up to date and drop ignore/attribute leftovers DOWNSTREAM.md: the baseline line points at .downstream/upstream-base and the v0.2.13 review instead of naming v0.2.8; the sentence about public model management goes; "CPA stays stopped" goes, the CPA service having been removed from the server. .gitignore: remove the two exceptions for the promptskills seed scripts, a directory that no longer exists. .gitattributes: the LF rules stay. Their comment now says what they are for, and *.ps1 goes: the only PowerShell files this fork ever tracked belonged to the remote skill registry and the prompt bundle. Co-Authored-By: Claude Opus 5.5 --- .gitattributes | 5 ++--- .gitignore | 2 -- DOWNSTREAM.md | 9 ++++----- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.gitattributes b/.gitattributes index 8ddee1fdfcde..829da726d62a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -21,8 +21,8 @@ backend/migrations/*.sql text eol=lf # Dockerfile Dockerfile text eol=lf -# Signed resources and review fingerprints must identify the same source bytes -# on developer Windows checkouts and Linux release builders. +# Keep these text files LF in every checkout, so a Windows working tree +# (core.autocrlf) holds the same bytes as the Linux CI and release builders. *.json text eol=lf *.css text eol=lf *.html text eol=lf @@ -33,7 +33,6 @@ Dockerfile text eol=lf *.py text eol=lf # Upstream stores this one script with CRLF; keep its bytes as they are. tools/check_pnpm_audit_exceptions.py -text -*.ps1 text eol=lf go.mod text eol=lf go.sum text eol=lf .gitattributes text eol=lf diff --git a/.gitignore b/.gitignore index 0fb7a07a0915..e08686baab8f 100644 --- a/.gitignore +++ b/.gitignore @@ -126,8 +126,6 @@ scripts !.github/scripts/*.py !backend/scripts/ !backend/scripts/resolve-version.sh -!/backend/internal/promptskills/registry/seed/tree/scripts/ -!/backend/internal/promptskills/registry/seed/tree/scripts/** .code-review-state #openspec/ code-reviews/ diff --git a/DOWNSTREAM.md b/DOWNSTREAM.md index de3175c88c13..62140621aea8 100644 --- a/DOWNSTREAM.md +++ b/DOWNSTREAM.md @@ -4,8 +4,8 @@ This fork maintains the `codexrip` patch set over official Sub2API releases. ## Source baseline -- Integrated official baseline: `v0.2.8`, commit `fd80b08c90b55edcad5b00171b53f08721d30da1`. -- Retained compatibility decisions: [upstream review](.downstream/upstream-review-v0.2.8.md). +- Integrated official baseline: the release recorded in `.downstream/upstream-base`. +- Retained compatibility decisions: [upstream review](.downstream/upstream-review-v0.2.13.md). - The operator workspace `docs/sub2api.md` owns the production version and image digest. A source merge or Release does not establish deployment completion. ## Native domains and account operations @@ -45,8 +45,7 @@ only that account/model. The account option `openai_prompt_cache_key_mode` 64 characters with its SHA-256 hex. Continuation, refusal recovery and destination-specific reasoning summaries remain supported. Account test model choices persist; API-key reveal requires the configured password. The account test -dialog keeps list position. Public model management remains retired; catalog -changes do not restore its routes or navigation. +dialog keeps list position. Quota storage, aggregation, cleanup and resets follow official semantics. Missing quota rows represent unlimited access; rows with three NULL limits are purged by @@ -68,7 +67,7 @@ The three `238_*` migrations retain separate filenames and checksums. automatic rollback. A failure preserves the runtime state for diagnosis. - SSH identity checks, fixed image validation, mutual exclusion and command error reporting remain required. Other services, networking, accounts, subscriptions - and manual routing stay within their existing configuration; CPA stays stopped. + and manual routing stay within their existing configuration. - Container/public health confirms availability, not actual model functionality. ## Upstream updates From e81a5d544b0571e2c1e3989ad3bf0e147fd6c5c5 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 11:57:41 +0800 Subject: [PATCH 08/21] build: put the backend builder stage and the candidate version back Root Dockerfile, backend builder stage, three lines back to upstream v0.2.13. bash is no longer installed: it was added for the plugin bundle script, which ran in a stage built on this one, and nothing here runs it (the one script the stage calls, backend/scripts/resolve-version.sh, is /bin/sh). GOOS and GOARCH come straight from TARGETOS and TARGETARCH again, not from two shell variables the plugin builds shared. The build comment is upstream's; the one it replaces dated from folding the plugins into the binary. What the built image runs does not change: the release and candidate builds both go through buildx with platforms linux/amd64, which sets TARGETARCH=amd64, the value the removed default supplied, and bash was only ever in the builder stage, which is not part of the image. downstream-verify.yml: the candidate image is built as VERSION=0.0.0-candidate again. The step that derived -codexrip.candidate existed so that the image build could verify the bundled plugins against that host version; the Dockerfile verifies no bundle now, and the candidate is only uploaded as a three-day artifact. Release images take their version from the tag as before. Differences from upstream's Dockerfile that remain: the vite build without type checking (the release reuses the pull request's validation), GOMEMLIMIT for the 768 MiB production limit, the THIRD_PARTY_NOTICES.md copy for the bundled fonts and icons, and /app/skill-registry, which production still mounts and a later change removes together with the mount. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/downstream-verify.yml | 7 +------ Dockerfile | 7 +++---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/downstream-verify.yml b/.github/workflows/downstream-verify.yml index 09ab20dcb0b3..bfec331a9da0 100644 --- a/.github/workflows/downstream-verify.yml +++ b/.github/workflows/downstream-verify.yml @@ -177,11 +177,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - name: Resolve candidate compatibility version - id: version - shell: bash - # Keep candidate versions distinct from every numbered codexrip release. - run: printf 'value=%s-codexrip.candidate\n' "$(tr -d '\r\n' < backend/cmd/server/VERSION)" >> "$GITHUB_OUTPUT" - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - name: Build candidate uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 @@ -192,7 +187,7 @@ jobs: push: false outputs: type=oci,dest=/tmp/sub2api-candidate.tar build-args: | - VERSION=${{ steps.version.outputs.value }} + VERSION=0.0.0-candidate COMMIT=${{ github.sha }} GOPROXY=https://proxy.golang.org,direct GOSUMDB=sum.golang.org diff --git a/Dockerfile b/Dockerfile index 86e36941468e..0f02abe4a5e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,7 +68,7 @@ ENV GOPROXY=${GOPROXY} ENV GOSUMDB=${GOSUMDB} # Install build dependencies -RUN apk add --no-cache git ca-certificates tzdata bash +RUN apk add --no-cache git ca-certificates tzdata WORKDIR /app/backend @@ -85,15 +85,14 @@ COPY backend/ ./ # Copy frontend dist from previous stage (must be after backend copy to avoid being overwritten) COPY --from=frontend-builder /app/backend/internal/web/dist ./internal/web/dist -# Build the host with its native domain modules. +# Build the binary (BuildType=release for CI builds, embed frontend) # Version precedence: build arg VERSION > exact git tag > cmd/server/VERSION RUN --mount=type=cache,id=sub2api-gomod,target=/go/pkg/mod \ --mount=type=cache,id=sub2api-gobuild,target=/root/.cache/go-build \ VERSION_VALUE="${VERSION}" && \ if [ -z "${VERSION_VALUE}" ]; then VERSION_VALUE="$(./scripts/resolve-version.sh)"; fi && \ DATE_VALUE="${DATE:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}" && \ - TARGET_OS="${TARGETOS:-linux}" && TARGET_ARCH="${TARGETARCH:-amd64}" && \ - CGO_ENABLED=0 GOOS=${TARGET_OS} GOARCH=${TARGET_ARCH} go build \ + CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build \ -tags embed \ -ldflags="-s -w -X main.Version=${VERSION_VALUE} -X main.Commit=${COMMIT} -X main.Date=${DATE_VALUE} -X main.BuildType=release" \ -trimpath \ From 79011a7f84d081ec3b1e5fda11293f41c2b9d670 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 11:57:42 +0800 Subject: [PATCH 09/21] test(migrations): delete the historical Cindy migration tests and their CI step The "Historical Cindy migration tests" step of Downstream backend selected tests from twelve files under backend/migrations. They assert the text of, or replay, migrations of the retired Cindy platform: the one-time account rewrites 207 to 209, the balance marker updates 210, 211 and 213, the platform projection of 229, 234 and 235, and the managed channel of 236. Migration 260 has since dropped the balance marker column, the projection table and functions, and the managed channel's triggers and functions. The step and the twelve files go; every migration file stays as it is, and the runner still refuses an applied migration whose checksum changed. Two of the files held more than the step selected, and all of it leaves with them: the 229 and 236 text checks and one more replay of 235, which belong to the same retired platform, and TestMigration235ModelAllowlistPreservesLegacyJSONByRenamingOnly, which is not Cindy: it pinned upstream's 235_group_model_allowlist.sql to a column rename. That file is byte-identical to upstream v0.2.13 and upstream has no such test. The unit selector in "Image, model list, and turn-state tests" loses Migration235 and Migration236, which matched only tests in a deleted file. Each remaining branch still selects at least one test. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/downstream-verify.yml | 7 +- ...earch_bridge_migration_integration_test.go | 93 ---- ...indy_alpha_search_bridge_migration_test.go | 28 -- ...lance_confirmation_reset_migration_test.go | 30 -- ...marker_reset_migration_integration_test.go | 315 -------------- ...ndy_balance_marker_reset_migration_test.go | 44 -- ...y_balance_marker_restore_migration_test.go | 35 -- ...nai_defaults_migration_integration_test.go | 136 ------ .../cindy_openai_defaults_migration_test.go | 30 -- ..._platform_v1_migration_integration_test.go | 400 ------------------ .../cindy_platform_v1_migration_test.go | 231 ---------- ...t_cache_hash_migration_integration_test.go | 94 ---- .../cindy_prompt_cache_hash_migration_test.go | 28 -- 13 files changed, 1 insertion(+), 1470 deletions(-) delete mode 100644 backend/migrations/cindy_alpha_search_bridge_migration_integration_test.go delete mode 100644 backend/migrations/cindy_alpha_search_bridge_migration_test.go delete mode 100644 backend/migrations/cindy_balance_confirmation_reset_migration_test.go delete mode 100644 backend/migrations/cindy_balance_marker_reset_migration_integration_test.go delete mode 100644 backend/migrations/cindy_balance_marker_reset_migration_test.go delete mode 100644 backend/migrations/cindy_balance_marker_restore_migration_test.go delete mode 100644 backend/migrations/cindy_openai_defaults_migration_integration_test.go delete mode 100644 backend/migrations/cindy_openai_defaults_migration_test.go delete mode 100644 backend/migrations/cindy_platform_v1_migration_integration_test.go delete mode 100644 backend/migrations/cindy_platform_v1_migration_test.go delete mode 100644 backend/migrations/cindy_prompt_cache_hash_migration_integration_test.go delete mode 100644 backend/migrations/cindy_prompt_cache_hash_migration_test.go diff --git a/.github/workflows/downstream-verify.yml b/.github/workflows/downstream-verify.yml index bfec331a9da0..d9bac55d926a 100644 --- a/.github/workflows/downstream-verify.yml +++ b/.github/workflows/downstream-verify.yml @@ -55,7 +55,7 @@ jobs: working-directory: backend run: | go test -p=1 -tags unit ./internal/repository ./internal/service ./internal/handler ./internal/handler/admin -run 'Test.*(CodexImageGenerationBridgeOverridePrecedence|TurnStateCommits|SchedulerCache|GatewayModels|WriteOpenAIModelsList|AccountHandlerGetAvailableModels|ForwardResponsesOllamaClampPreservesContinuationPolicy|AccountAvailableModels|FetchOpenAIAccountModels|SetAnthropicAPIKeyAuthHeader|OllamaCloud.*(MaxTokens|MaxOutputTokens|Bearer)|Clamps.*OllamaBase)' -count=1 - go test -p=1 -tags unit ./migrations -run 'Test.*(Migration222|Migration223|Migration224|Migration230|Migration231|Migration232|Migration235|Migration236|GroupModelAllowlistRepairMigration|ReleaseAcceptance)' -count=1 + go test -p=1 -tags unit ./migrations -run 'Test.*(Migration222|Migration223|Migration224|Migration230|Migration231|Migration232|GroupModelAllowlistRepairMigration|ReleaseAcceptance)' -count=1 - name: Request body recovery tests working-directory: backend run: go test -p=1 ./internal/pkg/httputil ./internal/handler -run 'Test(ReadRequestBodyWithPrealloc|ReadLenientJSONRequestBodyWithPrealloc|RequestBodyReadDiagnostics|ClassifyRequestContentEncoding)' -count=1 @@ -75,11 +75,6 @@ jobs: - name: Repository audit integration tests working-directory: backend run: go test -p=1 -tags integration ./internal/repository -run '^Test(PGXBatchInsertAuditAndSystemLogs|Migration236.*)$' -count=1 - - name: Historical Cindy migration tests - working-directory: backend - run: | - go test -p=1 ./migrations -run '^(TestMigration(207RestoresOnlyCindyNativeOpenAIModes|208UsesCindyPromptCacheHashOnly|209RestoresOnlyCindyAlphaSearchBridge|210ResetsOnlyLegacyCindyBalanceMarkers|211RestoresOnlyExactUnresolvedCindyBudgetMarkers|213ResetsOnlyStrictCindyBalanceMarkers)|TestMigration235RestrictsLedgerReplayToLifecycleExcludedRows)$' -count=1 - go test -p=1 -tags integration ./migrations -run '^(TestCindy(OpenAIDefaults|PromptCacheHash|AlphaSearchBridge|BalanceMarkerReset|BalanceMarkerRestore|BalanceConfirmationReset|PlatformProjectionRoundTrip)MigrationIsStrictAndIdempotent|TestMigration235PreservesMixedOpenAIGroupsAfterCanonicalReplay)$' -count=1 frontend: name: Downstream frontend diff --git a/backend/migrations/cindy_alpha_search_bridge_migration_integration_test.go b/backend/migrations/cindy_alpha_search_bridge_migration_integration_test.go deleted file mode 100644 index 7bb68715d113..000000000000 --- a/backend/migrations/cindy_alpha_search_bridge_migration_integration_test.go +++ /dev/null @@ -1,93 +0,0 @@ -//go:build integration - -package migrations_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - dbmigrations "github.com/Wei-Shaw/sub2api/migrations" -) - -func TestCindyAlphaSearchBridgeMigrationIsStrictAndIdempotent(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - CREATE TABLE accounts ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - platform TEXT NOT NULL, - type TEXT NOT NULL, - credentials JSONB NOT NULL DEFAULT '{}', - extra JSONB NOT NULL DEFAULT '{}', - status TEXT NOT NULL DEFAULT 'active', - deleted_at TIMESTAMPTZ - ); - INSERT INTO accounts (name, platform, type, credentials, extra, status, deleted_at) VALUES - ('cindy-active', 'openai', 'apikey', - '{"base_url":" https://API.LAXAROUTER.AI/ ","api_key":"fixture"}', - '{"openai_responses_mode":"force_responses","openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"sha256_64","ordinary":"kept"}', - 'disabled', NULL), - ('cindy-deleted', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"openai_alpha_search_mode":"disabled","ordinary":true}', 'error', NOW()), - ('cindy-already-bridge', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"openai_alpha_search_mode":"responses_web_search","openai_prompt_cache_key_mode":"sha256_64"}', - 'active', NULL), - ('ordinary', 'openai', 'apikey', - '{"base_url":"https://api.openai.com"}', - '{"openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"passthrough"}', - 'active', NULL), - ('cindy-path', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai/v1"}', - '{"openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"passthrough"}', - 'active', NULL), - ('cindy-oauth', 'openai', 'oauth', - '{"base_url":"https://api.laxarouter.ai"}', - '{"openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"passthrough"}', - 'active', NULL); - `)) - - alreadyBefore := readCindyMigrationAccount(t, ctx, db, "cindy-already-bridge") - migration, err := dbmigrations.FS.ReadFile("209_codexrip_restore_cindy_alpha_search_bridge.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - - active := readCindyMigrationAccount(t, ctx, db, "cindy-active") - require.JSONEq(t, `{ - "openai_responses_mode":"force_responses", - "openai_alpha_search_mode":"responses_web_search", - "openai_prompt_cache_key_mode":"sha256_64", - "ordinary":"kept" - }`, string(active.Extra)) - require.JSONEq(t, `{"base_url":" https://API.LAXAROUTER.AI/ ","api_key":"fixture"}`, string(active.Credentials)) - require.Equal(t, "disabled", active.Status) - require.False(t, active.Deleted) - - deleted := readCindyMigrationAccount(t, ctx, db, "cindy-deleted") - require.JSONEq(t, `{ - "openai_alpha_search_mode":"responses_web_search", - "ordinary":true - }`, string(deleted.Extra)) - require.Equal(t, "error", deleted.Status) - require.True(t, deleted.Deleted) - - alreadyAfter := readCindyMigrationAccount(t, ctx, db, "cindy-already-bridge") - require.Equal(t, alreadyBefore.RowVersion, alreadyAfter.RowVersion) - for _, name := range []string{"ordinary", "cindy-path", "cindy-oauth"} { - snapshot := readCindyMigrationAccount(t, ctx, db, name) - require.JSONEq(t, `{ - "openai_alpha_search_mode":"direct", - "openai_prompt_cache_key_mode":"passthrough" - }`, string(snapshot.Extra), name) - } - - firstRowVersion := active.RowVersion - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - second := readCindyMigrationAccount(t, ctx, db, "cindy-active") - require.Equal(t, firstRowVersion, second.RowVersion) - require.JSONEq(t, string(active.Extra), string(second.Extra)) -} diff --git a/backend/migrations/cindy_alpha_search_bridge_migration_test.go b/backend/migrations/cindy_alpha_search_bridge_migration_test.go deleted file mode 100644 index 81fcf86d588b..000000000000 --- a/backend/migrations/cindy_alpha_search_bridge_migration_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package migrations - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMigration209RestoresOnlyCindyAlphaSearchBridge(t *testing.T) { - raw, err := FS.ReadFile("209_codexrip_restore_cindy_alpha_search_bridge.sql") - require.NoError(t, err) - - sql := strings.ToLower(string(raw)) - require.Contains(t, sql, "update accounts") - require.Contains(t, sql, "set extra = jsonb_set") - require.Contains(t, sql, "'{openai_alpha_search_mode}'") - require.Contains(t, sql, "to_jsonb('responses_web_search'::text)") - require.Contains(t, sql, "platform = 'openai'") - require.Contains(t, sql, "type = 'apikey'") - require.Contains(t, sql, "lower(btrim(credentials->>'base_url'))") - require.Contains(t, sql, "is distinct from 'responses_web_search'") - require.NotContains(t, sql, "'{openai_prompt_cache_key_mode}'") - require.NotContains(t, sql, "'{openai_responses_mode}'") - require.NotContains(t, sql, "deleted_at is null") - require.NotContains(t, sql, "set credentials") - require.NotContains(t, sql, "updated_at =") -} diff --git a/backend/migrations/cindy_balance_confirmation_reset_migration_test.go b/backend/migrations/cindy_balance_confirmation_reset_migration_test.go deleted file mode 100644 index 748046f8822c..000000000000 --- a/backend/migrations/cindy_balance_confirmation_reset_migration_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package migrations - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMigration213ResetsOnlyStrictCindyBalanceMarkers(t *testing.T) { - raw, err := FS.ReadFile("213_codexrip_reset_unconfirmed_cindy_balance_markers.sql") - require.NoError(t, err) - - sql := strings.ToLower(string(raw)) - require.Contains(t, sql, "update accounts as a") - require.Contains(t, sql, "set cindy_balance_insufficient_at = null") - require.Contains(t, sql, "cindy_balance_insufficient_at is not null") - require.Contains(t, sql, "platform = 'openai'") - require.Contains(t, sql, "type = 'apikey'") - require.Contains(t, sql, "jsonb_typeof(a.credentials->'base_url') = 'string'") - require.Contains(t, sql, "lower(btrim(a.credentials->>'base_url'))") - require.Contains(t, sql, "'https://api.laxarouter.ai'") - require.Contains(t, sql, "'https://api.laxarouter.ai/'") - require.NotContains(t, sql, "set credentials") - require.NotContains(t, sql, "set extra") - require.NotContains(t, sql, "set status") - require.NotContains(t, sql, "set schedulable") - require.NotContains(t, sql, "deleted_at") - require.NotContains(t, sql, "ops_error_logs") -} diff --git a/backend/migrations/cindy_balance_marker_reset_migration_integration_test.go b/backend/migrations/cindy_balance_marker_reset_migration_integration_test.go deleted file mode 100644 index 41f9dd951c6c..000000000000 --- a/backend/migrations/cindy_balance_marker_reset_migration_integration_test.go +++ /dev/null @@ -1,315 +0,0 @@ -//go:build integration - -package migrations_test - -import ( - "context" - "database/sql" - "encoding/json" - "testing" - - "github.com/stretchr/testify/require" - - dbmigrations "github.com/Wei-Shaw/sub2api/migrations" -) - -type cindyBalanceResetSnapshot struct { - Credentials json.RawMessage - Extra json.RawMessage - Status string - Schedulable bool - Marked bool - Deleted bool - RowVersion string -} - -func TestCindyBalanceMarkerResetMigrationIsStrictAndIdempotent(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - CREATE TABLE accounts ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - platform TEXT NOT NULL, - type TEXT NOT NULL, - credentials JSONB NOT NULL DEFAULT '{}', - extra JSONB NOT NULL DEFAULT '{}', - status TEXT NOT NULL DEFAULT 'active', - schedulable BOOLEAN NOT NULL DEFAULT TRUE, - cindy_balance_insufficient_at TIMESTAMPTZ, - deleted_at TIMESTAMPTZ - ); - CREATE TABLE ops_error_logs ( - id BIGSERIAL PRIMARY KEY, - account_id BIGINT, - status_code INT, - upstream_status_code INT, - provider_error_type VARCHAR(64), - provider_error_code VARCHAR(64), - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() - ); - INSERT INTO accounts ( - name, platform, type, credentials, extra, status, schedulable, - cindy_balance_insufficient_at, deleted_at - ) VALUES - ('cindy-active', 'openai', 'apikey', - '{"base_url":" HTTPS://API.LAXAROUTER.AI/ ","api_key":"fixture"}', - '{"ordinary":"kept"}', 'disabled', FALSE, NOW(), NULL), - ('cindy-deleted', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"ordinary":true}', 'error', TRUE, NOW(), NOW()), - ('cindy-unmarked', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"ordinary":"untouched"}', 'active', TRUE, NULL, NULL), - ('ordinary', 'openai', 'apikey', - '{"base_url":"https://api.openai.com"}', '{}', 'active', TRUE, NOW(), NULL), - ('cindy-path', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai/v1"}', '{}', 'active', TRUE, NOW(), NULL), - ('cindy-oauth', 'openai', 'oauth', - '{"base_url":"https://api.laxarouter.ai"}', '{}', 'active', TRUE, NOW(), NULL); - - INSERT INTO ops_error_logs ( - account_id, status_code, upstream_status_code, - provider_error_type, provider_error_code, created_at - ) - SELECT id, 429, 429, 'budget_exceeded', NULL, cindy_balance_insufficient_at - FROM accounts WHERE name = 'cindy-active' - UNION ALL - SELECT id, 429, 429, 'budget_exceeded', '429', cindy_balance_insufficient_at - FROM accounts WHERE name = 'cindy-deleted'; - `)) - - beforeUnmarked := readCindyBalanceResetSnapshot(t, ctx, db, "cindy-unmarked") - migration, err := dbmigrations.FS.ReadFile("210_codexrip_reset_legacy_cindy_balance_markers.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - - active := readCindyBalanceResetSnapshot(t, ctx, db, "cindy-active") - require.False(t, active.Marked) - require.JSONEq(t, `{"base_url":" HTTPS://API.LAXAROUTER.AI/ ","api_key":"fixture"}`, string(active.Credentials)) - require.JSONEq(t, `{"ordinary":"kept"}`, string(active.Extra)) - require.Equal(t, "disabled", active.Status) - require.False(t, active.Schedulable) - require.False(t, active.Deleted) - - deleted := readCindyBalanceResetSnapshot(t, ctx, db, "cindy-deleted") - require.True(t, deleted.Marked) - require.Equal(t, "error", deleted.Status) - require.True(t, deleted.Schedulable) - require.True(t, deleted.Deleted) - - for _, name := range []string{"ordinary", "cindy-path", "cindy-oauth"} { - snapshot := readCindyBalanceResetSnapshot(t, ctx, db, name) - require.True(t, snapshot.Marked, name) - } - unmarked := readCindyBalanceResetSnapshot(t, ctx, db, "cindy-unmarked") - require.False(t, unmarked.Marked) - require.Equal(t, beforeUnmarked.RowVersion, unmarked.RowVersion) - - activeRowVersion := active.RowVersion - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - require.Equal(t, activeRowVersion, readCindyBalanceResetSnapshot(t, ctx, db, "cindy-active").RowVersion) - require.Equal(t, deleted.RowVersion, readCindyBalanceResetSnapshot(t, ctx, db, "cindy-deleted").RowVersion) -} - -func TestCindyBalanceMarkerRestoreMigrationIsStrictAndIdempotent(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - CREATE TABLE accounts ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - platform TEXT NOT NULL, - type TEXT NOT NULL, - credentials JSONB NOT NULL DEFAULT '{}', - extra JSONB NOT NULL DEFAULT '{}', - status TEXT NOT NULL DEFAULT 'active', - schedulable BOOLEAN NOT NULL DEFAULT TRUE, - cindy_balance_insufficient_at TIMESTAMPTZ, - deleted_at TIMESTAMPTZ - ); - CREATE TABLE ops_error_logs ( - id BIGSERIAL PRIMARY KEY, - account_id BIGINT, - status_code INT, - upstream_status_code INT, - upstream_error_detail TEXT, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() - ); - CREATE TABLE usage_logs ( - id BIGSERIAL PRIMARY KEY, - account_id BIGINT, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() - ); - INSERT INTO accounts ( - name, platform, type, credentials, extra, status, schedulable, - cindy_balance_insufficient_at, deleted_at - ) VALUES - ('exact-unresolved', 'openai', 'apikey', - '{"base_url":" HTTPS://API.LAXAROUTER.AI/ ","api_key":"fixture"}', - '{"ordinary":"kept"}', 'disabled', FALSE, NULL, NULL), - ('exact-recovered', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', '{}', 'active', TRUE, NULL, NULL), - ('numeric-code', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', '{}', 'active', TRUE, NULL, NULL), - ('message-only', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', '{}', 'active', TRUE, NULL, NULL), - ('exact-402', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', '{}', 'active', TRUE, NULL, NULL), - ('already-marked', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', '{}', 'active', TRUE, NOW() - INTERVAL '1 day', NULL), - ('deleted-exact', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', '{}', 'active', TRUE, NULL, NOW()), - ('ordinary-exact', 'openai', 'apikey', - '{"base_url":"https://api.openai.com"}', '{}', 'active', TRUE, NULL, NULL); - - INSERT INTO ops_error_logs ( - account_id, status_code, upstream_status_code, upstream_error_detail, created_at - ) - SELECT id, 429, 429, '{"error":{"type":"budget_exceeded","code":"429"}}', NOW() - INTERVAL '20 minutes' - FROM accounts WHERE name IN ('exact-unresolved', 'exact-recovered', 'already-marked', 'deleted-exact', 'ordinary-exact') - UNION ALL - SELECT id, 429, 429, '{"error":{"type":"budget_exceeded","code":429}}', NOW() - INTERVAL '20 minutes' - FROM accounts WHERE name = 'numeric-code' - UNION ALL - SELECT id, 429, 429, '{"error":{"message":"ExceededBudget: fixture over budget"}}', NOW() - INTERVAL '20 minutes' - FROM accounts WHERE name = 'message-only' - UNION ALL - SELECT id, 402, 402, '{"error":{"type":"budget_exceeded","code":"429"}}', NOW() - INTERVAL '20 minutes' - FROM accounts WHERE name = 'exact-402'; - - INSERT INTO usage_logs (account_id, created_at) - SELECT id, NOW() - INTERVAL '10 minutes' - FROM accounts WHERE name = 'exact-recovered'; - `)) - - beforeRecovered := readCindyBalanceResetSnapshot(t, ctx, db, "exact-recovered") - beforeAlreadyMarked := readCindyBalanceResetSnapshot(t, ctx, db, "already-marked") - migration, err := dbmigrations.FS.ReadFile("211_codexrip_restore_exact_cindy_budget_markers.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - - unresolved := readCindyBalanceResetSnapshot(t, ctx, db, "exact-unresolved") - require.True(t, unresolved.Marked) - require.JSONEq(t, `{"base_url":" HTTPS://API.LAXAROUTER.AI/ ","api_key":"fixture"}`, string(unresolved.Credentials)) - require.JSONEq(t, `{"ordinary":"kept"}`, string(unresolved.Extra)) - require.Equal(t, "disabled", unresolved.Status) - require.False(t, unresolved.Schedulable) - var markerMatchesExactLog bool - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT a.cindy_balance_insufficient_at = MAX(e.created_at) - FROM accounts a - JOIN ops_error_logs e ON e.account_id = a.id - WHERE a.name = 'exact-unresolved' - GROUP BY a.cindy_balance_insufficient_at - `).Scan(&markerMatchesExactLog)) - require.True(t, markerMatchesExactLog) - - for _, name := range []string{"exact-recovered", "numeric-code", "message-only", "exact-402", "deleted-exact", "ordinary-exact"} { - require.False(t, readCindyBalanceResetSnapshot(t, ctx, db, name).Marked, name) - } - require.True(t, readCindyBalanceResetSnapshot(t, ctx, db, "already-marked").Marked) - require.Equal(t, beforeRecovered.RowVersion, readCindyBalanceResetSnapshot(t, ctx, db, "exact-recovered").RowVersion) - require.Equal(t, beforeAlreadyMarked.RowVersion, readCindyBalanceResetSnapshot(t, ctx, db, "already-marked").RowVersion) - - unresolvedVersion := unresolved.RowVersion - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - require.Equal(t, unresolvedVersion, readCindyBalanceResetSnapshot(t, ctx, db, "exact-unresolved").RowVersion) - require.Equal(t, beforeRecovered.RowVersion, readCindyBalanceResetSnapshot(t, ctx, db, "exact-recovered").RowVersion) -} - -func TestCindyBalanceConfirmationResetMigrationIsStrictAndIdempotent(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - CREATE TABLE accounts ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - platform TEXT NOT NULL, - type TEXT NOT NULL, - credentials JSONB NOT NULL DEFAULT '{}', - extra JSONB NOT NULL DEFAULT '{}', - status TEXT NOT NULL DEFAULT 'active', - schedulable BOOLEAN NOT NULL DEFAULT TRUE, - cindy_balance_insufficient_at TIMESTAMPTZ, - deleted_at TIMESTAMPTZ - ); - INSERT INTO accounts ( - name, platform, type, credentials, extra, status, schedulable, - cindy_balance_insufficient_at, deleted_at - ) VALUES - ('cindy-active', 'openai', 'apikey', - '{"base_url":" HTTPS://API.LAXAROUTER.AI/ ","api_key":"fixture"}', - '{"ordinary":"kept"}', 'disabled', FALSE, NOW(), NULL), - ('cindy-deleted', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"ordinary":true}', 'error', TRUE, NOW(), NOW()), - ('cindy-unmarked', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"ordinary":"untouched"}', 'active', TRUE, NULL, NULL), - ('ordinary', 'openai', 'apikey', - '{"base_url":"https://api.openai.com"}', '{}', 'active', TRUE, NOW(), NULL), - ('cindy-path', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai/v1"}', '{}', 'active', TRUE, NOW(), NULL), - ('cindy-oauth', 'openai', 'oauth', - '{"base_url":"https://api.laxarouter.ai"}', '{}', 'active', TRUE, NOW(), NULL); - `)) - - beforeUnmarked := readCindyBalanceResetSnapshot(t, ctx, db, "cindy-unmarked") - migration, err := dbmigrations.FS.ReadFile("213_codexrip_reset_unconfirmed_cindy_balance_markers.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - - for _, name := range []string{"cindy-active", "cindy-deleted"} { - require.False(t, readCindyBalanceResetSnapshot(t, ctx, db, name).Marked, name) - } - active := readCindyBalanceResetSnapshot(t, ctx, db, "cindy-active") - require.JSONEq(t, `{"base_url":" HTTPS://API.LAXAROUTER.AI/ ","api_key":"fixture"}`, string(active.Credentials)) - require.JSONEq(t, `{"ordinary":"kept"}`, string(active.Extra)) - require.Equal(t, "disabled", active.Status) - require.False(t, active.Schedulable) - deleted := readCindyBalanceResetSnapshot(t, ctx, db, "cindy-deleted") - require.Equal(t, "error", deleted.Status) - require.True(t, deleted.Schedulable) - require.True(t, deleted.Deleted) - - for _, name := range []string{"ordinary", "cindy-path", "cindy-oauth"} { - require.True(t, readCindyBalanceResetSnapshot(t, ctx, db, name).Marked, name) - } - unmarked := readCindyBalanceResetSnapshot(t, ctx, db, "cindy-unmarked") - require.False(t, unmarked.Marked) - require.Equal(t, beforeUnmarked.RowVersion, unmarked.RowVersion) - - activeVersion := active.RowVersion - deletedVersion := deleted.RowVersion - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - require.Equal(t, activeVersion, readCindyBalanceResetSnapshot(t, ctx, db, "cindy-active").RowVersion) - require.Equal(t, deletedVersion, readCindyBalanceResetSnapshot(t, ctx, db, "cindy-deleted").RowVersion) -} - -func readCindyBalanceResetSnapshot( - t *testing.T, - ctx context.Context, - db interface { - QueryRowContext(context.Context, string, ...any) *sql.Row - }, - name string, -) cindyBalanceResetSnapshot { - t.Helper() - var snapshot cindyBalanceResetSnapshot - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT credentials, extra, status, schedulable, - cindy_balance_insufficient_at IS NOT NULL, - deleted_at IS NOT NULL, xmin::text - FROM accounts WHERE name = $1 - `, name).Scan( - &snapshot.Credentials, - &snapshot.Extra, - &snapshot.Status, - &snapshot.Schedulable, - &snapshot.Marked, - &snapshot.Deleted, - &snapshot.RowVersion, - )) - return snapshot -} diff --git a/backend/migrations/cindy_balance_marker_reset_migration_test.go b/backend/migrations/cindy_balance_marker_reset_migration_test.go deleted file mode 100644 index 93ef84498731..000000000000 --- a/backend/migrations/cindy_balance_marker_reset_migration_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package migrations - -import ( - "crypto/sha256" - "encoding/hex" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMigration210ResetsOnlyLegacyCindyBalanceMarkers(t *testing.T) { - raw, err := FS.ReadFile("210_codexrip_reset_legacy_cindy_balance_markers.sql") - require.NoError(t, err) - - sum := sha256.Sum256([]byte(strings.TrimSpace(string(raw)))) - require.Equal(t, - "ec98aa081586264383b35d9c3f8d4620b6a78836bba3644ff78c1c0fa0c3cd31", - hex.EncodeToString(sum[:]), - "migration 210 is already applied in production and must remain byte-stable", - ) - - sql := strings.ToLower(string(raw)) - require.Contains(t, sql, "update accounts") - require.Contains(t, sql, "set cindy_balance_insufficient_at = null") - require.Contains(t, sql, "cindy_balance_insufficient_at is not null") - require.Contains(t, sql, "platform = 'openai'") - require.Contains(t, sql, "type = 'apikey'") - require.Contains(t, sql, "jsonb_typeof(a.credentials->'base_url') = 'string'") - require.Contains(t, sql, "lower(btrim(a.credentials->>'base_url'))") - require.Contains(t, sql, "'https://api.laxarouter.ai'") - require.Contains(t, sql, "'https://api.laxarouter.ai/'") - require.Contains(t, sql, "from ops_error_logs as e") - require.Contains(t, sql, "coalesce(e.upstream_status_code, e.status_code) = 429") - require.Contains(t, sql, "e.provider_error_type = 'budget_exceeded'") - require.Contains(t, sql, "e.provider_error_code = '429'") - require.Contains(t, sql, "interval '2 minutes'") - require.NotContains(t, sql, "exceededbudget") - require.NotContains(t, sql, "set credentials") - require.NotContains(t, sql, "set extra") - require.NotContains(t, sql, "set status") - require.NotContains(t, sql, "set schedulable") - require.NotContains(t, sql, "deleted_at is null") -} diff --git a/backend/migrations/cindy_balance_marker_restore_migration_test.go b/backend/migrations/cindy_balance_marker_restore_migration_test.go deleted file mode 100644 index f83d155a5ab3..000000000000 --- a/backend/migrations/cindy_balance_marker_restore_migration_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package migrations - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMigration211RestoresOnlyExactUnresolvedCindyBudgetMarkers(t *testing.T) { - raw, err := FS.ReadFile("211_codexrip_restore_exact_cindy_budget_markers.sql") - require.NoError(t, err) - - sql := strings.ToLower(string(raw)) - require.Contains(t, sql, "update accounts") - require.Contains(t, sql, "set cindy_balance_insufficient_at = u.latest_exact_at") - require.Contains(t, sql, "cindy_balance_insufficient_at is null") - require.Contains(t, sql, "platform = 'openai'") - require.Contains(t, sql, "type = 'apikey'") - require.Contains(t, sql, "jsonb_typeof(a.credentials->'base_url') = 'string'") - require.Contains(t, sql, "e.upstream_error_detail is json") - require.Contains(t, sql, "coalesce(e.upstream_status_code, e.status_code) = 429") - require.Contains(t, sql, "jsonb_typeof(payload #> '{error,type}') = 'string'") - require.Contains(t, sql, "payload #>> '{error,type}' = 'budget_exceeded'") - require.Contains(t, sql, "jsonb_typeof(payload #> '{error,code}') = 'string'") - require.Contains(t, sql, "payload #>> '{error,code}' = '429'") - require.Contains(t, sql, "u.created_at > x.latest_exact_at") - require.NotContains(t, sql, "provider_error_type") - require.NotContains(t, sql, "provider_error_code") - require.NotContains(t, sql, "exceededbudget") - require.NotContains(t, sql, "set credentials") - require.NotContains(t, sql, "set extra") - require.NotContains(t, sql, "set status") - require.NotContains(t, sql, "set schedulable") -} diff --git a/backend/migrations/cindy_openai_defaults_migration_integration_test.go b/backend/migrations/cindy_openai_defaults_migration_integration_test.go deleted file mode 100644 index 96bd3825562a..000000000000 --- a/backend/migrations/cindy_openai_defaults_migration_integration_test.go +++ /dev/null @@ -1,136 +0,0 @@ -//go:build integration - -package migrations_test - -import ( - "context" - "database/sql" - "encoding/json" - "testing" - - "github.com/stretchr/testify/require" - - dbmigrations "github.com/Wei-Shaw/sub2api/migrations" -) - -type cindyMigrationAccountSnapshot struct { - Credentials json.RawMessage - Extra json.RawMessage - Status string - Deleted bool - RowVersion string -} - -func TestCindyOpenAIDefaultsMigrationIsStrictAndIdempotent(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - CREATE TABLE accounts ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - platform TEXT NOT NULL, - type TEXT NOT NULL, - credentials JSONB NOT NULL DEFAULT '{}', - extra JSONB NOT NULL DEFAULT '{}', - status TEXT NOT NULL DEFAULT 'active', - deleted_at TIMESTAMPTZ - ); - INSERT INTO accounts (name, platform, type, credentials, extra, status, deleted_at) VALUES - ('cindy-active', 'openai', 'apikey', - '{"base_url":" https://API.LAXAROUTER.AI/ ","api_key":"fixture"}', - '{"openai_responses_mode":"force_responses","openai_alpha_search_mode":"responses_web_search","openai_prompt_cache_key_mode":"sha256_64","ordinary":"kept"}', - 'disabled', NULL), - ('cindy-deleted', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"ordinary":true}', 'error', NOW()), - ('ordinary', 'openai', 'apikey', - '{"base_url":"https://api.openai.com"}', - '{"openai_alpha_search_mode":"responses_web_search","openai_prompt_cache_key_mode":"sha256_64"}', - 'active', NULL), - ('cindy-path', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai/v1"}', - '{"openai_alpha_search_mode":"responses_web_search","openai_prompt_cache_key_mode":"sha256_64"}', - 'active', NULL), - ('cindy-query', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai/?x=1"}', - '{"openai_alpha_search_mode":"responses_web_search","openai_prompt_cache_key_mode":"sha256_64"}', - 'active', NULL), - ('cindy-oauth', 'openai', 'oauth', - '{"base_url":"https://api.laxarouter.ai"}', - '{"openai_alpha_search_mode":"responses_web_search","openai_prompt_cache_key_mode":"sha256_64"}', - 'active', NULL), - ('cindy-uppercase-scheme', 'openai', 'apikey', - '{"base_url":"HTTPS://api.laxarouter.ai"}', - '{"openai_alpha_search_mode":"responses_web_search","openai_prompt_cache_key_mode":"sha256_64"}', - 'active', NULL); - `)) - - migration, err := dbmigrations.FS.ReadFile("207_codexrip_restore_cindy_openai_defaults.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - - active := readCindyMigrationAccount(t, ctx, db, "cindy-active") - require.JSONEq(t, `{ - "openai_responses_mode":"force_responses", - "openai_alpha_search_mode":"direct", - "openai_prompt_cache_key_mode":"passthrough", - "ordinary":"kept" - }`, string(active.Extra)) - require.JSONEq(t, `{"base_url":" https://API.LAXAROUTER.AI/ ","api_key":"fixture"}`, string(active.Credentials)) - require.Equal(t, "disabled", active.Status) - require.False(t, active.Deleted) - - deleted := readCindyMigrationAccount(t, ctx, db, "cindy-deleted") - require.JSONEq(t, `{ - "ordinary":true, - "openai_alpha_search_mode":"direct", - "openai_prompt_cache_key_mode":"passthrough" - }`, string(deleted.Extra)) - require.Equal(t, "error", deleted.Status) - require.True(t, deleted.Deleted) - - uppercaseScheme := readCindyMigrationAccount(t, ctx, db, "cindy-uppercase-scheme") - require.JSONEq(t, `{ - "openai_alpha_search_mode":"direct", - "openai_prompt_cache_key_mode":"passthrough" - }`, string(uppercaseScheme.Extra)) - - for _, name := range []string{ - "ordinary", "cindy-path", "cindy-query", "cindy-oauth", - } { - snapshot := readCindyMigrationAccount(t, ctx, db, name) - require.JSONEq(t, `{ - "openai_alpha_search_mode":"responses_web_search", - "openai_prompt_cache_key_mode":"sha256_64" - }`, string(snapshot.Extra), name) - } - - firstRowVersion := active.RowVersion - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - second := readCindyMigrationAccount(t, ctx, db, "cindy-active") - require.Equal(t, firstRowVersion, second.RowVersion) - require.JSONEq(t, string(active.Extra), string(second.Extra)) -} - -func readCindyMigrationAccount( - t *testing.T, - ctx context.Context, - db interface { - QueryRowContext(context.Context, string, ...any) *sql.Row - }, - name string, -) cindyMigrationAccountSnapshot { - t.Helper() - var snapshot cindyMigrationAccountSnapshot - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT credentials, extra, status, deleted_at IS NOT NULL, xmin::text - FROM accounts WHERE name = $1 - `, name).Scan( - &snapshot.Credentials, - &snapshot.Extra, - &snapshot.Status, - &snapshot.Deleted, - &snapshot.RowVersion, - )) - return snapshot -} diff --git a/backend/migrations/cindy_openai_defaults_migration_test.go b/backend/migrations/cindy_openai_defaults_migration_test.go deleted file mode 100644 index ec860640f6fa..000000000000 --- a/backend/migrations/cindy_openai_defaults_migration_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package migrations - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMigration207RestoresOnlyCindyNativeOpenAIModes(t *testing.T) { - raw, err := FS.ReadFile("207_codexrip_restore_cindy_openai_defaults.sql") - require.NoError(t, err) - - sql := strings.ToLower(string(raw)) - require.Contains(t, sql, "update accounts") - require.Contains(t, sql, "set extra = jsonb_set") - require.Contains(t, sql, "'{openai_alpha_search_mode}'") - require.Contains(t, sql, "to_jsonb('direct'::text)") - require.Contains(t, sql, "'{openai_prompt_cache_key_mode}'") - require.Contains(t, sql, "to_jsonb('passthrough'::text)") - require.Contains(t, sql, "platform = 'openai'") - require.Contains(t, sql, "type = 'apikey'") - require.Contains(t, sql, "lower(btrim(credentials->>'base_url'))") - require.Contains(t, sql, "'https://api.laxarouter.ai/'") - require.Contains(t, sql, "is distinct from 'direct'") - require.Contains(t, sql, "is distinct from 'passthrough'") - require.NotContains(t, sql, "deleted_at is null") - require.NotContains(t, sql, "set credentials") - require.NotContains(t, sql, "updated_at =") -} diff --git a/backend/migrations/cindy_platform_v1_migration_integration_test.go b/backend/migrations/cindy_platform_v1_migration_integration_test.go deleted file mode 100644 index ffb40d308865..000000000000 --- a/backend/migrations/cindy_platform_v1_migration_integration_test.go +++ /dev/null @@ -1,400 +0,0 @@ -//go:build integration - -package migrations_test - -import ( - "context" - "database/sql" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - dbmigrations "github.com/Wei-Shaw/sub2api/migrations" -) - -func TestCindyPlatformProjectionRoundTripMigrationIsStrictAndIdempotent(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, cindyPlatformPre229FixtureSQL)) - - migration229, err := dbmigrations.FS.ReadFile("229_cindy_platform_wire_identity.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration229))) - - assertCindyPlatformIdentity(t, ctx, db, "accounts", "legacy-cindy-active", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "legacy-cindy-active", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "ordinary-openai", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "ordinary-openai", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "legacy-cindy-with-deleted-ordinary", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "legacy-cindy-with-deleted-ordinary", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "deleted-ordinary-companion", "openai", "openai", "") - - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - INSERT INTO accounts - (id, name, platform, wire_platform, provider_profile, type, credentials, deleted_at) - VALUES - (3, 'cindy-soft-deleted', 'cindy', 'openai', 'cindy_laxa_v1', 'apikey', - '{"base_url":"https://api.laxarouter.ai","api_key":"fixture-deleted"}', NOW()); - INSERT INTO groups - (id, name, platform, wire_platform, provider_profile, fallback_group_id, deleted_at) - VALUES - (3, 'cindy-empty', 'cindy', 'openai', 'cindy_laxa_v1', NULL, NULL), - (4, 'cindy-soft-deleted', 'cindy', 'openai', 'cindy_laxa_v1', NULL, NOW()); - - SELECT * FROM project_cindy_platform_v1_to_legacy(); - - INSERT INTO accounts - (id, name, platform, type, credentials, deleted_at) - VALUES - (5, 'new-legacy-cindy', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai/","api_key":"fixture-new"}', NULL); - INSERT INTO groups - (id, name, platform, fallback_group_id, deleted_at) - VALUES - (5, 'new-legacy-cindy', 'openai', NULL, NULL); - INSERT INTO account_groups (account_id, group_id) VALUES (5, 5); - `)) - - for _, tc := range []struct { - table string - name string - }{ - {table: "accounts", name: "legacy-cindy-active"}, - {table: "accounts", name: "cindy-soft-deleted"}, - {table: "groups", name: "legacy-cindy-active"}, - {table: "groups", name: "cindy-empty"}, - {table: "groups", name: "cindy-soft-deleted"}, - } { - assertCindyPlatformIdentity(t, ctx, db, tc.table, tc.name, "openai", "openai", "") - } - - migration234, err := dbmigrations.FS.ReadFile("234_fix_cindy_platform_projection_round_trip.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration234))) - assertCindyProjectionForwardState(t, ctx, db) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration234))) - assertCindyProjectionForwardState(t, ctx, db) - - require.NoError(t, execRemoteSkillSQL(ctx, db, `SELECT * FROM project_cindy_platform_v1_to_legacy()`)) - for _, name := range []string{"legacy-cindy-active", "cindy-soft-deleted"} { - assertCindyPlatformIdentity(t, ctx, db, "accounts", name, "openai", "openai", "") - } - for _, name := range []string{"legacy-cindy-active", "cindy-empty", "cindy-soft-deleted", "legacy-cindy-with-deleted-ordinary"} { - assertCindyPlatformIdentity(t, ctx, db, "groups", name, "openai", "openai", "") - } - assertCindyPlatformIdentity(t, ctx, db, "accounts", "legacy-cindy-with-deleted-ordinary", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "deleted-ordinary-companion", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "new-legacy-cindy", "openai", "", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "new-legacy-cindy", "openai", "", "") - - require.NoError(t, execRemoteSkillSQL(ctx, db, `SELECT * FROM project_cindy_platform_v1_from_legacy()`)) - assertCindyProjectionForwardState(t, ctx, db) - - var promotedAccounts, promotedGroups int64 - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT promoted_accounts, promoted_groups - FROM project_cindy_platform_v1_from_legacy() - `).Scan(&promotedAccounts, &promotedGroups)) - require.Zero(t, promotedAccounts) - require.Zero(t, promotedGroups) -} - -func TestMigration235PreservesMixedOpenAIGroupsAfterCanonicalReplay(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, cindyPlatformPre229FixtureSQL)) - - migration229, err := dbmigrations.FS.ReadFile("229_cindy_platform_wire_identity.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration229))) - assertCindyPlatformIdentity(t, ctx, db, "accounts", "legacy-cindy-active", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "legacy-cindy-active", "cindy", "openai", "cindy_laxa_v1") - - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - INSERT INTO accounts - (id, name, platform, wire_platform, provider_profile, type, credentials, deleted_at) - VALUES - (3, 'cindy-soft-deleted', 'cindy', 'openai', 'cindy_laxa_v1', 'apikey', - '{"base_url":"https://api.laxarouter.ai","api_key":"fixture-deleted"}', NOW()); - INSERT INTO groups - (id, name, platform, wire_platform, provider_profile, fallback_group_id, deleted_at) - VALUES - (3, 'cindy-empty', 'cindy', 'openai', 'cindy_laxa_v1', NULL, NULL), - (4, 'cindy-soft-deleted', 'cindy', 'openai', 'cindy_laxa_v1', NULL, NOW()); - - SELECT * FROM project_cindy_platform_v1_to_legacy(); - - INSERT INTO accounts - (id, name, platform, type, credentials, deleted_at) - VALUES - (8, 'ordinary-member-added-after-rollback', 'openai', 'apikey', - '{"base_url":"https://api.openai.com","api_key":"fixture-added-ordinary"}', NULL), - (9, 'independent-pure-cindy', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai","api_key":"fixture-independent-cindy"}', NULL); - INSERT INTO groups - (id, name, platform, fallback_group_id, deleted_at) - VALUES - (9, 'independent-pure-cindy', 'openai', NULL, NULL); - INSERT INTO account_groups (account_id, group_id) VALUES - (8, 2), - (9, 9); - `)) - - // Migration 234 replays the canonical ledger before it discovers current - // topology, reproducing the mixed-group promotion that 235 must repair. - migration234, err := dbmigrations.FS.ReadFile("234_fix_cindy_platform_projection_round_trip.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration234))) - assertCindyPlatformIdentity(t, ctx, db, "accounts", "legacy-cindy-active", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "legacy-cindy-active", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "ordinary-member-added-after-rollback", "openai", "", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "independent-pure-cindy", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "independent-pure-cindy", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "cindy-soft-deleted", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "cindy-empty", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "cindy-soft-deleted", "cindy", "openai", "cindy_laxa_v1") - - migration235, err := dbmigrations.FS.ReadFile("235_preserve_mixed_openai_cindy_groups.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration235))) - - assertCindyPlatformIdentity(t, ctx, db, "accounts", "legacy-cindy-active", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "legacy-cindy-active", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "ordinary-member-added-after-rollback", "openai", "", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "independent-pure-cindy", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "independent-pure-cindy", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "cindy-soft-deleted", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "cindy-empty", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "cindy-soft-deleted", "cindy", "openai", "cindy_laxa_v1") - - var ledgerRows int - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT COUNT(*) - FROM cindy_platform_v1_projection - WHERE (entity_type, entity_id) IN (('account', 2), ('group', 2), ('account', 9), ('group', 9)) - `).Scan(&ledgerRows)) - require.Equal(t, 4, ledgerRows) - - require.NoError(t, execRemoteSkillSQL(ctx, db, `SELECT * FROM project_cindy_platform_v1_to_legacy()`)) - assertCindyPlatformIdentity(t, ctx, db, "accounts", "legacy-cindy-active", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "legacy-cindy-active", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "independent-pure-cindy", "openai", "", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "independent-pure-cindy", "openai", "", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "cindy-soft-deleted", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "cindy-empty", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "cindy-soft-deleted", "openai", "openai", "") - - require.NoError(t, execRemoteSkillSQL(ctx, db, `SELECT * FROM project_cindy_platform_v1_from_legacy()`)) - assertCindyPlatformIdentity(t, ctx, db, "accounts", "legacy-cindy-active", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "legacy-cindy-active", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "independent-pure-cindy", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "independent-pure-cindy", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "cindy-soft-deleted", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "cindy-empty", "cindy", "openai", "cindy_laxa_v1") - assertCindyPlatformIdentity(t, ctx, db, "groups", "cindy-soft-deleted", "cindy", "openai", "cindy_laxa_v1") - - for range 2 { - var promotedAccounts, promotedGroups int64 - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT promoted_accounts, promoted_groups - FROM project_cindy_platform_v1_from_legacy() - `).Scan(&promotedAccounts, &promotedGroups)) - require.Zero(t, promotedAccounts) - require.Zero(t, promotedGroups) - } -} - -func TestMigration235SkipsStaleSoftDeletedAccountLedgerEntries(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, cindyPlatformPre229FixtureSQL)) - - for _, migrationName := range []string{ - "229_cindy_platform_wire_identity.sql", - "234_fix_cindy_platform_projection_round_trip.sql", - } { - migrationSQL, err := dbmigrations.FS.ReadFile(migrationName) - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migrationSQL))) - } - - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - INSERT INTO accounts - (id, name, platform, wire_platform, provider_profile, type, credentials, deleted_at) - VALUES - (10, 'ledger-retyped-before-delete', 'cindy', 'openai', 'cindy_laxa_v1', 'apikey', - '{"base_url":"https://api.laxarouter.ai","api_key":"fixture-retyped"}', NULL), - (11, 'ledger-repointed-before-delete', 'cindy', 'openai', 'cindy_laxa_v1', 'apikey', - '{"base_url":"https://api.laxarouter.ai","api_key":"fixture-repointed"}', NULL), - (12, 'ledger-non-string-url-before-delete', 'cindy', 'openai', 'cindy_laxa_v1', 'apikey', - '{"base_url":"https://api.laxarouter.ai","api_key":"fixture-non-string"}', NULL), - (13, 'ledger-unchanged-laxa-before-delete', 'cindy', 'openai', 'cindy_laxa_v1', 'apikey', - '{"base_url":" HTTPS://API.LAXAROUTER.AI/ ","api_key":"fixture-unchanged"}', NULL); - - SELECT * FROM project_cindy_platform_v1_to_legacy(); - - UPDATE accounts - SET type = 'oauth', deleted_at = NOW() - WHERE id = 10; - UPDATE accounts - SET credentials = '{"base_url":"https://api.openai.com","api_key":"fixture-repointed"}', - deleted_at = NOW() - WHERE id = 11; - UPDATE accounts - SET credentials = '{"base_url":17,"api_key":"fixture-non-string"}', - deleted_at = NOW() - WHERE id = 12; - UPDATE accounts - SET deleted_at = NOW() - WHERE id = 13; - `)) - - for _, name := range []string{ - "ledger-retyped-before-delete", - "ledger-repointed-before-delete", - "ledger-non-string-url-before-delete", - "ledger-unchanged-laxa-before-delete", - } { - assertCindyPlatformIdentity(t, ctx, db, "accounts", name, "openai", "openai", "") - } - - migration235, err := dbmigrations.FS.ReadFile("235_preserve_mixed_openai_cindy_groups.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration235))) - - for _, name := range []string{ - "ledger-retyped-before-delete", - "ledger-repointed-before-delete", - "ledger-non-string-url-before-delete", - } { - assertCindyPlatformIdentity(t, ctx, db, "accounts", name, "openai", "openai", "") - } - assertCindyPlatformIdentity(t, ctx, db, "accounts", "ledger-unchanged-laxa-before-delete", "cindy", "openai", "cindy_laxa_v1") - - var promotedAccounts, promotedGroups int64 - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT promoted_accounts, promoted_groups - FROM project_cindy_platform_v1_from_legacy() - `).Scan(&promotedAccounts, &promotedGroups)) - require.Zero(t, promotedAccounts) - require.Zero(t, promotedGroups) -} - -func assertCindyProjectionForwardState(t *testing.T, ctx context.Context, db *sql.DB) { - t.Helper() - for _, tc := range []struct { - table string - name string - }{ - {table: "accounts", name: "legacy-cindy-active"}, - {table: "accounts", name: "cindy-soft-deleted"}, - {table: "accounts", name: "new-legacy-cindy"}, - {table: "accounts", name: "legacy-cindy-with-deleted-ordinary"}, - {table: "groups", name: "legacy-cindy-active"}, - {table: "groups", name: "cindy-empty"}, - {table: "groups", name: "cindy-soft-deleted"}, - {table: "groups", name: "new-legacy-cindy"}, - {table: "groups", name: "legacy-cindy-with-deleted-ordinary"}, - } { - assertCindyPlatformIdentity(t, ctx, db, tc.table, tc.name, "cindy", "openai", "cindy_laxa_v1") - } - assertCindyPlatformIdentity(t, ctx, db, "accounts", "ordinary-openai", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "accounts", "deleted-ordinary-companion", "openai", "openai", "") - assertCindyPlatformIdentity(t, ctx, db, "groups", "ordinary-openai", "openai", "openai", "") - - var deletedCompanionProjectionRows int - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT COUNT(*) - FROM cindy_platform_v1_projection p - JOIN accounts a ON a.id = p.entity_id - WHERE p.entity_type = 'account' - AND a.name = 'deleted-ordinary-companion' - `).Scan(&deletedCompanionProjectionRows)) - require.Zero(t, deletedCompanionProjectionRows) - - var pending int - require.NoError(t, db.QueryRowContext(ctx, ` - SELECT COUNT(*) - FROM cindy_platform_v1_projection p - LEFT JOIN accounts a ON p.entity_type = 'account' AND a.id = p.entity_id - LEFT JOIN groups g ON p.entity_type = 'group' AND g.id = p.entity_id - WHERE (p.entity_type = 'account' AND - (a.platform, a.wire_platform, a.provider_profile) IS NOT DISTINCT FROM - (p.original_platform, p.original_wire_platform, p.original_provider_profile)) - OR (p.entity_type = 'group' AND - (g.platform, g.wire_platform, g.provider_profile) IS NOT DISTINCT FROM - (p.original_platform, p.original_wire_platform, p.original_provider_profile)) - `).Scan(&pending)) - require.Zero(t, pending) -} - -func assertCindyPlatformIdentity( - t *testing.T, - ctx context.Context, - db *sql.DB, - table string, - name string, - wantPlatform string, - wantWirePlatform string, - wantProviderProfile string, -) { - t.Helper() - require.Contains(t, []string{"accounts", "groups"}, table) - var platform, wirePlatform, providerProfile string - err := db.QueryRowContext(ctx, fmt.Sprintf(` - SELECT platform, wire_platform, provider_profile - FROM %s - WHERE name = $1 - `, table), name).Scan(&platform, &wirePlatform, &providerProfile) - require.NoError(t, err) - require.Equal(t, wantPlatform, platform, "%s %s platform", table, name) - require.Equal(t, wantWirePlatform, wirePlatform, "%s %s wire platform", table, name) - require.Equal(t, wantProviderProfile, providerProfile, "%s %s provider profile", table, name) -} - -const cindyPlatformPre229FixtureSQL = ` -CREATE TABLE groups ( - id BIGINT PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - platform VARCHAR(50) NOT NULL, - fallback_group_id BIGINT, - deleted_at TIMESTAMPTZ -); - -CREATE TABLE accounts ( - id BIGINT PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - platform VARCHAR(50) NOT NULL, - type VARCHAR(50) NOT NULL, - credentials JSONB NOT NULL DEFAULT '{}', - deleted_at TIMESTAMPTZ -); - -CREATE TABLE account_groups ( - account_id BIGINT NOT NULL REFERENCES accounts(id), - group_id BIGINT NOT NULL REFERENCES groups(id), - PRIMARY KEY (account_id, group_id) -); - -INSERT INTO groups (id, name, platform, fallback_group_id, deleted_at) VALUES - (1, 'ordinary-openai', 'openai', NULL, NULL), - (2, 'legacy-cindy-active', 'openai', NULL, NULL), - (6, 'legacy-cindy-with-deleted-ordinary', 'openai', NULL, NULL); - -INSERT INTO accounts (id, name, platform, type, credentials, deleted_at) VALUES - (1, 'ordinary-openai', 'openai', 'apikey', - '{"base_url":"https://api.openai.com","api_key":"fixture-ordinary"}', NULL), - (2, 'legacy-cindy-active', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai","api_key":"fixture-cindy"}', NULL), - (6, 'legacy-cindy-with-deleted-ordinary', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai","api_key":"fixture-cindy-with-deleted-companion"}', NULL), - (7, 'deleted-ordinary-companion', 'openai', 'apikey', - '{"base_url":"https://api.openai.com","api_key":"fixture-deleted-ordinary"}', NOW()); - -INSERT INTO account_groups (account_id, group_id) VALUES - (1, 1), - (2, 2), - (6, 6), - (7, 6); -` diff --git a/backend/migrations/cindy_platform_v1_migration_test.go b/backend/migrations/cindy_platform_v1_migration_test.go deleted file mode 100644 index 3114d4d65d49..000000000000 --- a/backend/migrations/cindy_platform_v1_migration_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package migrations - -import ( - "io/fs" - "os" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMigration229ProjectsOnlyExactLegacyCindyAndHasReversibleFunctions(t *testing.T) { - raw, err := FS.ReadFile("229_cindy_platform_wire_identity.sql") - require.NoError(t, err) - sql := string(raw) - lower := strings.ToLower(sql) - - for _, fragment := range []string{ - "ADD COLUMN IF NOT EXISTS wire_platform", - "ADD COLUMN IF NOT EXISTS provider_profile", - "CREATE TABLE IF NOT EXISTS cindy_platform_v1_projection", - "jsonb_typeof(a.credentials->'base_url') = 'string'", - "'https://api.laxarouter.ai', 'https://api.laxarouter.ai/'", - "SET platform = 'cindy'", - "wire_platform = 'openai'", - "provider_profile = 'cindy_laxa_v1'", - "project_cindy_platform_v1_from_legacy", - "project_cindy_platform_v1_to_legacy", - "fallback_group_id IS NOT NULL", - } { - require.Contains(t, sql, fragment) - } - - require.NotContains(t, lower, "like '%laxarouter.ai%'") - require.NotContains(t, lower, "position('laxarouter.ai'") - require.NotContains(t, lower, "create trigger") - require.NotContains(t, lower, "constraint trigger") - require.NotContains(t, lower, "auth_cache") - require.NotContains(t, lower, "remediation") - require.NotContains(t, lower, "startup") -} - -func TestMigration229UsesReservedPostUpstreamNumber(t *testing.T) { - entries, err := FS.ReadDir(".") - require.NoError(t, err) - found := false - for _, entry := range entries { - if entry.Name() == "229_cindy_platform_wire_identity.sql" { - found = true - } - } - require.True(t, found) -} - -func TestMigration235ModelAllowlistPreservesLegacyJSONByRenamingOnly(t *testing.T) { - raw, err := FS.ReadFile("235_group_model_allowlist.sql") - require.NoError(t, err) - - var lines []string - for _, line := range strings.Split(string(raw), "\n") { - if !strings.HasPrefix(strings.TrimSpace(line), "--") { - lines = append(lines, line) - } - } - - // A column rename preserves every legacy JSON value, including enabled-empty - // lists and old wildcard entries. Do not silently disable or normalize them. - const renameOnly = ` -DO $$ -BEGIN - IF EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_schema = 'public' - AND table_name = 'groups' - AND column_name = 'models_list_config' - ) AND NOT EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_schema = 'public' - AND table_name = 'groups' - AND column_name = 'model_allowlist' - ) THEN - ALTER TABLE groups RENAME COLUMN models_list_config TO model_allowlist; - END IF; -END -$$; -COMMENT ON COLUMN groups.model_allowlist IS - 'Group model allowlist: constrains both model listing responses and request admission'; -` - require.Equal(t, - strings.Join(strings.Fields(renameOnly), " "), - strings.Join(strings.Fields(strings.Join(lines, "\n")), " "), - "the official migration must rename the column without rewriting legacy JSON") -} - -func TestMigration235RestrictsLedgerReplayToLifecycleExcludedRows(t *testing.T) { - matches, err := fs.Glob(FS, "235_*.sql") - require.NoError(t, err) - // Migration identity is the complete filename, not its numeric prefix. - require.Contains(t, matches, "235_group_model_allowlist.sql") - require.Contains(t, matches, "235_preserve_mixed_openai_cindy_groups.sql") - - raw, err := FS.ReadFile("235_preserve_mixed_openai_cindy_groups.sql") - require.NoError(t, err) - sql := strings.ToLower(string(raw)) - - beginAt := strings.Index(sql, "begin;") - restoreAt := strings.Index(sql, "select * from project_cindy_platform_v1_to_legacy()") - redefineAt := strings.Index(sql, "create or replace function project_cindy_platform_v1_from_legacy()") - forwardAt := strings.LastIndex(sql, "select * from project_cindy_platform_v1_from_legacy()") - commitAt := strings.LastIndex(sql, "commit;") - require.GreaterOrEqual(t, beginAt, 0) - require.Greater(t, restoreAt, beginAt) - require.Greater(t, redefineAt, restoreAt) - require.Greater(t, forwardAt, redefineAt) - require.Greater(t, commitAt, forwardAt) - functionEnd := redefineAt + strings.Index(sql[redefineAt:], "$$;") - require.Greater(t, functionEnd, redefineAt) - forwardFunction := sql[redefineAt:functionEnd] - require.Contains(t, forwardFunction, "return query") - require.Contains(t, forwardFunction, "from project_cindy_platform_v1_discover_legacy()") - require.Contains(t, forwardFunction, "cindy_platform_v1_projection") - require.Contains(t, forwardFunction, "a.deleted_at is not null") - require.Contains(t, forwardFunction, "g.deleted_at is not null or not exists") - require.NotContains(t, sql, "create temp table") - require.NotContains(t, sql, "insert into account_groups") - require.NotContains(t, sql, "update account_groups") - require.NotContains(t, sql, "delete from account_groups") - require.NotContains(t, sql, "delete from cindy_platform_v1_projection") - - for _, workflow := range []string{ - "../../.github/workflows/downstream-verify.yml", - } { - raw, err := os.ReadFile(workflow) - require.NoError(t, err) - contents := string(raw) - require.Contains(t, contents, "TestMigration235RestrictsLedgerReplayToLifecycleExcludedRows") - require.Contains(t, contents, "TestMigration235PreservesMixedOpenAIGroupsAfterCanonicalReplay") - } -} - -func TestMigration236DefinesManagedCindyChannelAndDurableInvalidation(t *testing.T) { - matches, err := fs.Glob(FS, "236_*.sql") - require.NoError(t, err) - require.Equal(t, []string{ - "236_bind_strict_cindy_groups_to_catalog_channel.sql", - "236_group_model_allowlist_repair.sql", - }, matches) - - raw, err := FS.ReadFile("236_bind_strict_cindy_groups_to_catalog_channel.sql") - require.NoError(t, err) - sql := strings.ToLower(string(raw)) - - for _, fragment := range []string{ - "set local lock_timeout = '5s'", - "set local statement_timeout = '60s'", - "lock table groups, accounts, account_groups", - "cindy_catalog_managed", - "cindy_laxa_v1", - "fallback_group_id_on_invalid_request is null", - "join accounts strict_member", - "insert into channel_groups", - "insert into scheduler_outbox", - "enqueue_group_api_key_auth_cache_invalidations", - "trg_groups_cindy_channel_topology", - "trg_accounts_cindy_identity_auth_cache_invalidation", - "after update of platform, wire_platform, provider_profile, type, credentials, status, deleted_at on accounts", - "old.fallback_group_id_on_invalid_request is not distinct from new.fallback_group_id_on_invalid_request", - "channel_account_stats_pricing_rules", - "guard_managed_cindy_channel", - "raise exception", - } { - require.Contains(t, sql, fragment) - } - require.NotRegexp(t, `where\s+g\.id\s*=\s*\d+`, sql) - require.NotContains(t, sql, "platform = 'openai' and cmp.platform = 'openai'") - require.NotContains(t, sql, "gpt-5.6") - require.NotContains(t, sql, "insert into channel_model_pricing") -} - -func TestMigration236PreservesCompleteGroupAuthInvalidationCoverage(t *testing.T) { - raw, err := FS.ReadFile("236_bind_strict_cindy_groups_to_catalog_channel.sql") - require.NoError(t, err) - sql := strings.ToLower(string(raw)) - - for _, field := range []string{ - "status", "is_exclusive", "allow_image_generation", "platform", - "subscription_type", "rate_multiplier", "peak_rate_enabled", "peak_start", - "peak_end", "peak_rate_multiplier", "profit_control_enabled", - "profit_min_margin", "profit_safety_buffer", "deleted_at", - "wire_platform", "provider_profile", "fallback_group_id", - "fallback_group_id_on_invalid_request", - } { - require.Contains(t, sql, - "old."+field+" is not distinct from new."+field, - "missing durable group auth invalidation field %s", field) - } - require.Contains(t, sql, "after update or delete on groups") - require.NotContains(t, sql, "create trigger trg_groups_auth_cache_invalidation\nafter update of") -} - -func TestMigration236TrimsReservedManagedChannelNames(t *testing.T) { - raw, err := FS.ReadFile("236_bind_strict_cindy_groups_to_catalog_channel.sql") - require.NoError(t, err) - sql := strings.ToLower(string(raw)) - - require.Contains(t, sql, "lower(btrim(c.name)) = lower('cindy catalog')") - require.Contains(t, sql, "old_reserved := lower(btrim(old.name)) = lower('cindy catalog')") - require.Contains(t, sql, "new_reserved := lower(btrim(new.name)) = lower('cindy catalog')") - require.NotContains(t, sql, "lower(c.name) = lower('cindy catalog')") -} - -func TestMigration236IntegrationFixtureIncludesGroupAuthTriggerColumns(t *testing.T) { - raw, err := os.ReadFile("cindy_channel_binding_migration_integration_test.go") - require.NoError(t, err) - fixture := strings.ToLower(string(raw)) - - for _, column := range []string{ - "allow_image_generation boolean not null default false", - "subscription_type varchar(20) not null default 'standard'", - "rate_multiplier decimal(10, 4) not null default 1.0", - "peak_rate_enabled boolean not null default false", - "peak_start varchar(5) not null default ''", - "peak_end varchar(5) not null default ''", - "peak_rate_multiplier decimal(10,4) not null default 1.0", - "profit_control_enabled boolean not null default false", - "profit_min_margin decimal(10,4) not null default 0", - "profit_safety_buffer decimal(10,4) not null default 0", - } { - require.Contains(t, fixture, column) - } -} diff --git a/backend/migrations/cindy_prompt_cache_hash_migration_integration_test.go b/backend/migrations/cindy_prompt_cache_hash_migration_integration_test.go deleted file mode 100644 index bd807db83000..000000000000 --- a/backend/migrations/cindy_prompt_cache_hash_migration_integration_test.go +++ /dev/null @@ -1,94 +0,0 @@ -//go:build integration - -package migrations_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - dbmigrations "github.com/Wei-Shaw/sub2api/migrations" -) - -func TestCindyPromptCacheHashMigrationIsStrictAndIdempotent(t *testing.T) { - ctx := context.Background() - db, _ := remoteSkillMigrationTestDatabase(t) - require.NoError(t, execRemoteSkillSQL(ctx, db, ` - CREATE TABLE accounts ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - platform TEXT NOT NULL, - type TEXT NOT NULL, - credentials JSONB NOT NULL DEFAULT '{}', - extra JSONB NOT NULL DEFAULT '{}', - status TEXT NOT NULL DEFAULT 'active', - deleted_at TIMESTAMPTZ - ); - INSERT INTO accounts (name, platform, type, credentials, extra, status, deleted_at) VALUES - ('cindy-active', 'openai', 'apikey', - '{"base_url":" https://API.LAXAROUTER.AI/ ","api_key":"fixture"}', - '{"openai_responses_mode":"force_responses","openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"passthrough","ordinary":"kept"}', - 'disabled', NULL), - ('cindy-deleted', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"openai_alpha_search_mode":"direct","ordinary":true}', 'error', NOW()), - ('cindy-already-hashed', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai"}', - '{"openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"sha256_64"}', - 'active', NULL), - ('ordinary', 'openai', 'apikey', - '{"base_url":"https://api.openai.com"}', - '{"openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"passthrough"}', - 'active', NULL), - ('cindy-path', 'openai', 'apikey', - '{"base_url":"https://api.laxarouter.ai/v1"}', - '{"openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"passthrough"}', - 'active', NULL), - ('cindy-oauth', 'openai', 'oauth', - '{"base_url":"https://api.laxarouter.ai"}', - '{"openai_alpha_search_mode":"direct","openai_prompt_cache_key_mode":"passthrough"}', - 'active', NULL); - `)) - - alreadyBefore := readCindyMigrationAccount(t, ctx, db, "cindy-already-hashed") - migration, err := dbmigrations.FS.ReadFile("208_codexrip_use_cindy_prompt_cache_hash.sql") - require.NoError(t, err) - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - - active := readCindyMigrationAccount(t, ctx, db, "cindy-active") - require.JSONEq(t, `{ - "openai_responses_mode":"force_responses", - "openai_alpha_search_mode":"direct", - "openai_prompt_cache_key_mode":"sha256_64", - "ordinary":"kept" - }`, string(active.Extra)) - require.JSONEq(t, `{"base_url":" https://API.LAXAROUTER.AI/ ","api_key":"fixture"}`, string(active.Credentials)) - require.Equal(t, "disabled", active.Status) - require.False(t, active.Deleted) - - deleted := readCindyMigrationAccount(t, ctx, db, "cindy-deleted") - require.JSONEq(t, `{ - "openai_alpha_search_mode":"direct", - "openai_prompt_cache_key_mode":"sha256_64", - "ordinary":true - }`, string(deleted.Extra)) - require.Equal(t, "error", deleted.Status) - require.True(t, deleted.Deleted) - - alreadyAfter := readCindyMigrationAccount(t, ctx, db, "cindy-already-hashed") - require.Equal(t, alreadyBefore.RowVersion, alreadyAfter.RowVersion) - for _, name := range []string{"ordinary", "cindy-path", "cindy-oauth"} { - snapshot := readCindyMigrationAccount(t, ctx, db, name) - require.JSONEq(t, `{ - "openai_alpha_search_mode":"direct", - "openai_prompt_cache_key_mode":"passthrough" - }`, string(snapshot.Extra), name) - } - - firstRowVersion := active.RowVersion - require.NoError(t, execRemoteSkillSQL(ctx, db, string(migration))) - second := readCindyMigrationAccount(t, ctx, db, "cindy-active") - require.Equal(t, firstRowVersion, second.RowVersion) - require.JSONEq(t, string(active.Extra), string(second.Extra)) -} diff --git a/backend/migrations/cindy_prompt_cache_hash_migration_test.go b/backend/migrations/cindy_prompt_cache_hash_migration_test.go deleted file mode 100644 index 487123504fd1..000000000000 --- a/backend/migrations/cindy_prompt_cache_hash_migration_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package migrations - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMigration208UsesCindyPromptCacheHashOnly(t *testing.T) { - raw, err := FS.ReadFile("208_codexrip_use_cindy_prompt_cache_hash.sql") - require.NoError(t, err) - - sql := strings.ToLower(string(raw)) - require.Contains(t, sql, "update accounts") - require.Contains(t, sql, "set extra = jsonb_set") - require.Contains(t, sql, "'{openai_prompt_cache_key_mode}'") - require.Contains(t, sql, "to_jsonb('sha256_64'::text)") - require.Contains(t, sql, "platform = 'openai'") - require.Contains(t, sql, "type = 'apikey'") - require.Contains(t, sql, "lower(btrim(credentials->>'base_url'))") - require.Contains(t, sql, "is distinct from 'sha256_64'") - require.NotContains(t, sql, "'{openai_alpha_search_mode}'") - require.NotContains(t, sql, "'{openai_responses_mode}'") - require.NotContains(t, sql, "deleted_at is null") - require.NotContains(t, sql, "set credentials") - require.NotContains(t, sql, "updated_at =") -} From d964018c684f94c8404b573d0e42fac3f0041127 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 11:57:43 +0800 Subject: [PATCH 10/21] docs: delete the plugin-era records and the earlier integration records No workflow, script or test reads any of these files. .downstream/coverage-v0.2.7.json and .md, refresh-coverage.mjs with its test, and implementation-v0.2.7.md: the ownership and review inventory of the seven-plugin release, taken against upstream v0.2.7. The generator can only rewrite that inventory; it assigns paths to the plugins of that release, and the inventory names more files that no longer exist than files that do. .superpowers/: the task ledger of the August work on Cindy groups and the capability catalogue. .downstream/cindy-catalog-refresh-20260905.json and -20260911.json: probe records for the fixed Cindy catalogue; Cindy accounts take their models from model sync. .downstream/upstream-0.2.0-overlap-review.md and upstream-review-v0.2.1, .5, .6, .8, .9, .10 and .11: integrations that are no longer the baseline. upstream-review-v0.2.13.md, the record of the current one, stays. .gitattributes loses *.mjs, which matched only the two deleted scripts. .downstream/upstream-risk.json still lists these paths. It is the risk classifier's output for the v0.2.13 integration, the gate recomputes it from the commits it records, and the next sync rewrites it. Co-Authored-By: Claude Opus 5.5 --- .../cindy-catalog-refresh-20260905.json | 17 - .../cindy-catalog-refresh-20260911.json | 16 - .downstream/coverage-v0.2.7.json | 42926 ---------------- .downstream/coverage-v0.2.7.md | 40 - .downstream/implementation-v0.2.7.md | 186 - .downstream/refresh-coverage.mjs | 148 - .downstream/refresh-coverage.test.mjs | 54 - .downstream/upstream-0.2.0-overlap-review.md | 188 - .downstream/upstream-review-v0.2.1.md | 59 - .downstream/upstream-review-v0.2.10.md | 46 - .downstream/upstream-review-v0.2.11.md | 67 - .downstream/upstream-review-v0.2.5.md | 155 - .downstream/upstream-review-v0.2.6.md | 41 - .downstream/upstream-review-v0.2.8.md | 47 - .downstream/upstream-review-v0.2.9.md | 37 - .gitattributes | 1 - .../cindy-group-account-ops-v180/progress.md | 82 - .../task-3-report.md | 213 - .../task-4b-report.md | 35 - .../task-5-report.md | 68 - .../task-6-report.md | 40 - 21 files changed, 44466 deletions(-) delete mode 100644 .downstream/cindy-catalog-refresh-20260905.json delete mode 100644 .downstream/cindy-catalog-refresh-20260911.json delete mode 100644 .downstream/coverage-v0.2.7.json delete mode 100644 .downstream/coverage-v0.2.7.md delete mode 100644 .downstream/implementation-v0.2.7.md delete mode 100644 .downstream/refresh-coverage.mjs delete mode 100644 .downstream/refresh-coverage.test.mjs delete mode 100644 .downstream/upstream-0.2.0-overlap-review.md delete mode 100644 .downstream/upstream-review-v0.2.1.md delete mode 100644 .downstream/upstream-review-v0.2.10.md delete mode 100644 .downstream/upstream-review-v0.2.11.md delete mode 100644 .downstream/upstream-review-v0.2.5.md delete mode 100644 .downstream/upstream-review-v0.2.6.md delete mode 100644 .downstream/upstream-review-v0.2.8.md delete mode 100644 .downstream/upstream-review-v0.2.9.md delete mode 100644 .superpowers/sdd/cindy-group-account-ops-v180/progress.md delete mode 100644 .superpowers/sdd/cindy-group-account-ops-v180/task-3-report.md delete mode 100644 .superpowers/sdd/cindy-group-account-ops-v180/task-4b-report.md delete mode 100644 .superpowers/sdd/cindy-group-account-ops-v180/task-5-report.md delete mode 100644 .superpowers/sdd/cindy-group-account-ops-v180/task-6-report.md diff --git a/.downstream/cindy-catalog-refresh-20260905.json b/.downstream/cindy-catalog-refresh-20260905.json deleted file mode 100644 index e2ac2f9b8be1..000000000000 --- a/.downstream/cindy-catalog-refresh-20260905.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "observedAt": "2026-09-05T09:52:03Z", - "catalogSha256": "9f27de4e91b54efe44c9ac8107882cbe971dc94be3ea715bfd6dfaae7fd2d07a", - "catalogCount": 15, - "accountsUsed": 1, - "nativeRequests": 8, - "retries": 0, - "accountSwitches": 0, - "metadataSource": "makecindy/cindy@81e383b5acb43ff4c7ff388a4103f77492c530e6", - "probeEvidence": "us-capability-probe-2026-09-05_095203_090290.log", - "models": [ - {"id": "google/gemini-3.8-flash", "responsesSearchStatus": 200, "responsesVerified": true, "searchVerified": true, "messagesStatus": 200, "messagesVerified": true, "metadataComplete": false, "public": false}, - {"id": "meta/muse-spark-1.3", "responsesSearchStatus": 200, "responsesVerified": true, "searchVerified": true, "messagesStatus": 200, "messagesVerified": true, "metadataComplete": false, "public": false}, - {"id": "openai/gpt-6-astra", "responsesSearchStatus": 200, "responsesVerified": true, "searchVerified": true, "messagesStatus": 400, "messagesVerified": false, "metadataComplete": true, "public": true}, - {"id": "tencent/hy4-preview", "responsesSearchStatus": 0, "responsesVerified": false, "searchVerified": false, "messagesStatus": 200, "messagesVerified": true, "metadataComplete": false, "public": false} - ] -} diff --git a/.downstream/cindy-catalog-refresh-20260911.json b/.downstream/cindy-catalog-refresh-20260911.json deleted file mode 100644 index 04aec9c24104..000000000000 --- a/.downstream/cindy-catalog-refresh-20260911.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "observedAt": "2026-09-11T16:00:22Z", - "catalogSha256": "38045af0a5a90c360ba44013d90a1ccbff65c903db7f9b99701c30ce15ca8821", - "catalogCount": 17, - "accountsUsed": 1, - "nativeRequests": 0, - "retries": 0, - "accountSwitches": 0, - "metadataSource": "makecindy/cindy@2128cd45e08e3419a36ad474d8c01e42a34ea328", - "probeEvidence": "us-capability-probe-2026-09-11_160022_753793.log", - "models": [ - {"id": "deepseek/deepseek-flash", "responsesVerified": false, "searchVerified": false, "messagesVerified": false, "metadataComplete": false, "public": false}, - {"id": "openai/gpt-image-2.5-flare", "responsesVerified": false, "searchVerified": false, "messagesVerified": false, "metadataComplete": false, "public": false}, - {"id": "openai/gpt-image-2.5-sunburst", "responsesVerified": false, "searchVerified": false, "messagesVerified": false, "metadataComplete": false, "public": false} - ] -} diff --git a/.downstream/coverage-v0.2.7.json b/.downstream/coverage-v0.2.7.json deleted file mode 100644 index 13582a2bb5f5..000000000000 --- a/.downstream/coverage-v0.2.7.json +++ /dev/null @@ -1,42926 +0,0 @@ -{ - "schema_version": 3, - "upstream_base": "aea725f2ea644d5592d0bbb1d63b607efa7e200a", - "basis_commit": "beb74d35bf938d9e6299fd08809cd7341c8fc4d7", - "scope": "Current Sub2API downstream source and working tree. Candidate ownership does not establish completed review. Root maintenance, independent services and Worker require a separate audit.", - "source_digest": "97557326168c20f43dda0ecfac9c87ec5b250b50834c36c957049664b0435eab", - "digest_excludes": [ - "the inventory itself uses a derived structural fingerprint; deletions bind the upstream blob" - ], - "total_paths": 2479, - "generated_assets_and_locks": 83, - "review_complete": false, - "pending_paths": [ - ".downstream/README.md", - ".downstream/implementation-v0.2.7.md", - ".downstream/refresh-coverage.mjs", - ".downstream/upstream-0.2.0-overlap-review.md", - ".downstream/upstream-base", - ".downstream/upstream-review-v0.2.1.md", - ".downstream/upstream-review-v0.2.5.md", - ".downstream/upstream-review-v0.2.6.md", - ".downstream/upstream-risk.json", - ".github/scripts/test_upstream_automation_contract.py", - ".github/workflows/backend-ci.yml", - ".github/workflows/downstream-verify.yml", - ".github/workflows/security-scan.yml", - "backend/cmd/package-plugin/main.go", - "backend/cmd/package-plugin/verify.go", - "backend/internal/config/config.go", - "backend/internal/config/config_test.go", - "backend/internal/config/image_studio_feature_flags.go", - "backend/internal/handler/admin/account_batch_testing.go", - "backend/internal/handler/admin/account_codex_import.go", - "backend/internal/handler/admin/account_create_profile_test.go", - "backend/internal/handler/admin/account_data.go", - "backend/internal/handler/admin/account_edit_test.go", - "backend/internal/handler/admin/account_handler.go", - "backend/internal/handler/admin/account_handler_available_models_test.go", - "backend/internal/handler/admin/account_handler_mixed_channel_test.go", - "backend/internal/handler/admin/account_job_execution.go", - "backend/internal/handler/admin/account_job_handler.go", - "backend/internal/handler/admin/account_taxonomy.go", - "backend/internal/handler/admin/account_test_plan.go", - "backend/internal/handler/admin/cindy_balance_probe_handler.go", - "backend/internal/handler/admin/cindy_balance_probe_handler_test.go", - "backend/internal/handler/admin/group_cindy_split.go", - "backend/internal/handler/admin/group_cindy_split_test.go", - "backend/internal/handler/admin/plugin_account_views_test.go", - "backend/internal/handler/admin/plugin_handler.go", - "backend/internal/handler/admin/plugin_resources.go", - "backend/internal/handler/admin/plugin_update.go", - "backend/internal/handler/admin/scheduled_test_handler.go", - "backend/internal/handler/cindy_balance_handler_failover_test.go", - "backend/internal/handler/cindy_balance_terminal_test.go", - "backend/internal/handler/dto/account_edit_state_test.go", - "backend/internal/handler/dto/mappers.go", - "backend/internal/handler/dto/types.go", - "backend/internal/handler/gateway_handler.go", - "backend/internal/handler/gateway_models_test.go", - "backend/internal/handler/openai_gateway_cindy_count_tokens_test.go", - "backend/internal/handler/openai_gateway_cindy_image_validation_test.go", - "backend/internal/handler/openai_gateway_handler_test.go", - "backend/internal/handler/openai_gateway_ws_model_allowlist_test.go", - "backend/internal/handler/openai_legacy_cindy_continuation.go", - "backend/internal/handler/openai_legacy_cindy_continuation_test.go", - "backend/internal/handler/openai_profit_slot_recheck_test.go", - "backend/internal/handler/remote_skill_handler.go", - "backend/internal/handler/remote_skill_handler_test.go", - "backend/internal/payment/provider/alipay_test.go", - "backend/internal/payment/provider/easypay_refund_test.go", - "backend/internal/payment/provider/wxpay_test.go", - "backend/internal/pkg/antigravity/client_test.go", - "backend/internal/pkg/antigravity/oauth_test.go", - "backend/internal/pkg/antigravity/request_transformer_test.go", - "backend/internal/pkg/apicompat/agent_stream_terminal_test.go", - "backend/internal/pkg/apicompat/agent_tool_history_test.go", - "backend/internal/pkg/apicompat/anthropic_responses_fidelity_test.go", - "backend/internal/pkg/apicompat/anthropic_responses_test.go", - "backend/internal/pkg/apicompat/anthropic_to_responses.go", - "backend/internal/pkg/apicompat/chat_terminal.go", - "backend/internal/pkg/apicompat/responses_to_chatcompletions.go", - "backend/internal/repository/account_edit_fence_integration_test.go", - "backend/internal/repository/account_job_cindy_mutation.go", - "backend/internal/repository/account_job_cindy_mutation_test.go", - "backend/internal/repository/account_job_repo.go", - "backend/internal/repository/account_repo_cindy_balance.go", - "backend/internal/repository/account_repo_cindy_balance_integration_test.go", - "backend/internal/repository/account_repo_cindy_balance_test.go", - "backend/internal/repository/account_repo_cindy_group_identity_integration_test.go", - "backend/internal/repository/account_repo_cindy_group_identity_test.go", - "backend/internal/repository/account_repo_cindy_identity_lifecycle_integration_test.go", - "backend/internal/repository/account_view_fence_test.go", - "backend/internal/repository/business_system_prompt_repository.go", - "backend/internal/repository/business_system_prompt_repository_test.go", - "backend/internal/repository/business_system_prompt_revision_bus.go", - "backend/internal/repository/business_system_prompt_revision_bus_test.go", - "backend/internal/repository/cindy_account_view_atomic_test.go", - "backend/internal/repository/cindy_balance_probe_finalize_integration_test.go", - "backend/internal/repository/cindy_balance_probe_lifecycle_integration_test.go", - "backend/internal/repository/cindy_balance_probe_repo.go", - "backend/internal/repository/cindy_balance_probe_repo_test.go", - "backend/internal/repository/cindy_group_identity.go", - "backend/internal/repository/cindy_health_repo.go", - "backend/internal/repository/cindy_health_repo_test.go", - "backend/internal/repository/gateway_cache_cindy_balance_test.go", - "backend/internal/repository/group_repo_cindy_health_test.go", - "backend/internal/repository/group_repo_cindy_split.go", - "backend/internal/repository/group_repo_cindy_split_test.go", - "backend/internal/repository/migrations_historical_preflight.go", - "backend/internal/repository/migrations_historical_preflight_test.go", - "backend/internal/repository/migrations_runner.go", - "backend/internal/repository/minimax_cindy_quota_migration_integration_test.go", - "backend/internal/repository/plugin_bundle.go", - "backend/internal/repository/plugin_extension_state.go", - "backend/internal/repository/plugin_host_io_admission_integration_test.go", - "backend/internal/repository/plugin_registry_tx.go", - "backend/internal/repository/plugin_update.go", - "backend/internal/repository/plugin_update_integration_test.go", - "backend/internal/repository/remote_skill_job_expiry_test.go", - "backend/internal/repository/remote_skill_registry_repository.go", - "backend/internal/repository/remote_skill_registry_repository_test.go", - "backend/internal/repository/remote_skill_registry_revision_bus.go", - "backend/internal/server/api_contract_test.go", - "backend/internal/server/routes/admin.go", - "backend/internal/server/routes/gateway_models_pinned_test.go", - "backend/internal/service/account_edit_bulk.go", - "backend/internal/service/account_edit_codec.go", - "backend/internal/service/account_job.go", - "backend/internal/service/account_job_batch_test_runtime.go", - "backend/internal/service/account_job_plugin.go", - "backend/internal/service/account_job_test.go", - "backend/internal/service/account_quota_window_state.go", - "backend/internal/service/account_quota_window_state_test.go", - "backend/internal/service/account_reasoning_policy_test.go", - "backend/internal/service/account_test_models_test.go", - "backend/internal/service/account_test_prompt.go", - "backend/internal/service/account_test_prompt_test.go", - "backend/internal/service/account_test_reasoning_test.go", - "backend/internal/service/account_test_reasoning_wire_test.go", - "backend/internal/service/account_test_service.go", - "backend/internal/service/account_test_service_cn_adaptive.go", - "backend/internal/service/account_test_service_openai_compact_test.go", - "backend/internal/service/account_test_service_openai_image_test.go", - "backend/internal/service/account_test_service_openai_test.go", - "backend/internal/service/account_test_service_opencode_go.go", - "backend/internal/service/account_usage_service.go", - "backend/internal/service/admin_account.go", - "backend/internal/service/admin_account_cindy_probe.go", - "backend/internal/service/admin_account_cindy_probe_test.go", - "backend/internal/service/admin_account_taxonomy.go", - "backend/internal/service/admin_cindy_balance.go", - "backend/internal/service/admin_cindy_balance_test.go", - "backend/internal/service/admin_cindy_group_split.go", - "backend/internal/service/admin_cindy_group_split_test.go", - "backend/internal/service/admin_service.go", - "backend/internal/service/admin_service_bulk_update_test.go", - "backend/internal/service/antigravity_gateway_compat_stream.go", - "backend/internal/service/business_system_prompt_account_scope_test.go", - "backend/internal/service/business_system_prompt_bundle.go", - "backend/internal/service/business_system_prompt_bundle_test.go", - "backend/internal/service/business_system_prompt_cache_identity_test.go", - "backend/internal/service/business_system_prompt_composition.go", - "backend/internal/service/business_system_prompt_composition_test.go", - "backend/internal/service/business_system_prompt_gateway_test.go", - "backend/internal/service/business_system_prompt_offline_integration_test.go", - "backend/internal/service/business_system_prompt_service.go", - "backend/internal/service/business_system_prompt_service_test.go", - "backend/internal/service/business_system_prompt_test.go", - "backend/internal/service/business_system_prompt_turn_cache_test.go", - "backend/internal/service/channel_cindy_managed_crud_test.go", - "backend/internal/service/cindy_account_test_plan.go", - "backend/internal/service/cindy_alpha_search_plan.go", - "backend/internal/service/cindy_capability_catalog.go", - "backend/internal/service/cindy_catalog_snapshot.go", - "backend/internal/service/cindy_group.go", - "backend/internal/service/cindy_group_identity_test.go", - "backend/internal/service/cindy_group_materialized_test.go", - "backend/internal/service/cindy_health.go", - "backend/internal/service/cindy_health_service_test.go", - "backend/internal/service/cindy_identity.go", - "backend/internal/service/cindy_identity_test.go", - "backend/internal/service/cindy_image_pricing_test.go", - "backend/internal/service/cindy_native_count_tokens_test.go", - "backend/internal/service/cindy_native_image_snapshot_test.go", - "backend/internal/service/cindy_native_messages_test.go", - "backend/internal/service/cindy_pricing_snapshot.go", - "backend/internal/service/cindy_rollout_testmain_test.go", - "backend/internal/service/cindy_snapshot_pricing_second_review_test.go", - "backend/internal/service/cindy_terminal_scheduling_isolation_test.go", - "backend/internal/service/cindy_text_billing.go", - "backend/internal/service/cindy_text_billing_test.go", - "backend/internal/service/cindy_v4_catalog_contract_test.go", - "backend/internal/service/cindy_v4_catalog_fixture_test.go", - "backend/internal/service/cn_provider_balance_check_service_test.go", - "backend/internal/service/codex_ticket_lifecycle.go", - "backend/internal/service/codex_ticket_manual.go", - "backend/internal/service/codex_ticket_manual_test.go", - "backend/internal/service/codex_ticket_plugin.go", - "backend/internal/service/codex_ticket_proxy.go", - "backend/internal/service/codex_ticket_proxy_test.go", - "backend/internal/service/deepseek_pricing.go", - "backend/internal/service/deepseek_pricing_test.go", - "backend/internal/service/domain_constants.go", - "backend/internal/service/domain_constants_test.go", - "backend/internal/service/gateway_anthropic_apikey_passthrough_test.go", - "backend/internal/service/gateway_anthropic_passthrough.go", - "backend/internal/service/gateway_count_tokens.go", - "backend/internal/service/gateway_forward_as_chat_completions.go", - "backend/internal/service/gateway_model_availability.go", - "backend/internal/service/gateway_model_availability_test.go", - "backend/internal/service/gateway_multiplatform_test.go", - "backend/internal/service/gemini_chat_completions_compat_service.go", - "backend/internal/service/model_context_capacity_catalog.go", - "backend/internal/service/openai_alpha_search.go", - "backend/internal/service/openai_alpha_search_cindy_native_first_test.go", - "backend/internal/service/openai_apikey_responses_probe_test.go", - "backend/internal/service/openai_bulk_account_settings.go", - "backend/internal/service/openai_cindy_continuation.go", - "backend/internal/service/openai_cindy_continuation_ingress_test.go", - "backend/internal/service/openai_cindy_continuation_test.go", - "backend/internal/service/openai_cindy_http_wsv2.go", - "backend/internal/service/openai_cindy_http_wsv2_test.go", - "backend/internal/service/openai_codex_client_identity_test.go", - "backend/internal/service/openai_codex_ticket.go", - "backend/internal/service/openai_codex_ticket_scheduler_test.go", - "backend/internal/service/openai_codex_ticket_test.go", - "backend/internal/service/openai_codex_transform_test.go", - "backend/internal/service/openai_gateway_chat_completions_anthropic_native.go", - "backend/internal/service/openai_gateway_deepseek_chat_reasoning_test.go", - "backend/internal/service/openai_gateway_scheduling.go", - "backend/internal/service/openai_gateway_usage.go", - "backend/internal/service/openai_images.go", - "backend/internal/service/openai_load_sticky_privacy_test.go", - "backend/internal/service/openai_model_mapping_test.go", - "backend/internal/service/openai_model_not_supported_test.go", - "backend/internal/service/openai_oauth_429_classifier.go", - "backend/internal/service/openai_reasoning_recovery.go", - "backend/internal/service/openai_ws_v2_passthrough_lifecycle_test.go", - "backend/internal/service/plugin_account_edit.go", - "backend/internal/service/plugin_account_edit_test.go", - "backend/internal/service/plugin_account_views.go", - "backend/internal/service/plugin_broker_scope_test.go", - "backend/internal/service/plugin_cindy_codex_test.go", - "backend/internal/service/plugin_cindy_probe.go", - "backend/internal/service/plugin_cindy_probe_test.go", - "backend/internal/service/plugin_codex_identity.go", - "backend/internal/service/plugin_extension_package_test.go", - "backend/internal/service/plugin_extension_state.go", - "backend/internal/service/plugin_host_services_broker_test.go", - "backend/internal/service/plugin_image_bridge.go", - "backend/internal/service/plugin_image_bridge_test.go", - "backend/internal/service/plugin_jobs.go", - "backend/internal/service/plugin_manager.go", - "backend/internal/service/plugin_operation.go", - "backend/internal/service/plugin_operation_admission_test.go", - "backend/internal/service/plugin_package.go", - "backend/internal/service/plugin_prompt_management.go", - "backend/internal/service/plugin_resources.go", - "backend/internal/service/prompt_domain_runtime.go", - "backend/internal/service/prompt_domain_runtime_test.go", - "backend/internal/service/provider_identity_admin_test.go", - "backend/internal/service/quota_estimate.go", - "backend/internal/service/ratelimit_service_cindy_balance_test.go", - "backend/internal/service/ratelimit_service_openai_test.go", - "backend/internal/service/remote_skill_prompt.go", - "backend/internal/service/remote_skill_prompt_test.go", - "backend/internal/service/remote_skill_publication.go", - "backend/internal/service/remote_skill_publication_test.go", - "backend/internal/service/remote_skill_registry.go", - "backend/internal/service/remote_skill_registry_filesystem.go", - "backend/internal/service/remote_skill_registry_filesystem_test.go", - "backend/internal/service/remote_skill_registry_manifest.go", - "backend/internal/service/remote_skill_registry_manifest_test.go", - "backend/internal/service/remote_skill_registry_source.go", - "backend/internal/service/remote_skill_registry_source_provenance_test.go", - "backend/internal/service/remote_skill_registry_source_test.go", - "backend/internal/service/remote_skill_registry_test.go", - "backend/internal/service/remote_skill_registry_validation.go", - "backend/internal/service/remote_skill_seed_fixture_test.go", - "backend/internal/service/responses_chat_protocol_callers_test.go", - "backend/internal/service/setting_codex_ticket_test.go", - "backend/internal/service/testdata/cindy_free_catalog_2026-08-29.json", - "backend/internal/service/testdata/cindy_free_catalog_2026-09-11.json", - "backend/migrations/230_account_credential_identities.sql", - "backend/migrations/232_admin_account_jobs.sql", - "backend/migrations/233_image_studio_jobs.sql", - "backend/migrations/237_add_minimax_platform.sql", - "backend/migrations/238_opencode_go_platform.sql", - "backend/migrations/239_codexrip_release_acceptance_api_key_leases.sql", - "backend/migrations/240_admin_account_capabilities.sql", - "backend/migrations/242_retire_public_model_manager.sql", - "backend/migrations/243_codex_fingerprint_device_default.sql", - "backend/migrations/244_codex_ticket_lifecycle.sql", - "backend/migrations/245_codex_ticket_account_status_independent.sql", - "backend/migrations/account_credential_identity_migration_test.go", - "backend/migrations/account_jobs_slim_migration_test.go", - "backend/migrations/business_system_prompt_codex_skill_hybrid_migration_test.go", - "backend/migrations/business_system_prompt_managed_source_migration_test.go", - "backend/migrations/business_system_prompt_remote_skill_migration_test.go", - "backend/migrations/business_system_prompt_skill_bundles_migration_test.go", - "backend/migrations/business_system_prompts_migration_test.go", - "backend/migrations/image_studio_jobs_migration_test.go", - "backend/migrations/minimax_platform_migration_test.go", - "backend/migrations/opencode_go_platform_migration_test.go", - "backend/migrations/release_acceptance_api_key_lease_migration_test.go", - "backend/migrations/remote_skill_registry_migration_test.go", - "backend/migrations/remote_skill_sources_migration_integration_test.go", - "backend/pkg/extensionapi/ui/account-edit.ts", - "backend/pkg/extensionapi/ui/account-view.ts", - "backend/pkg/extensionapi/ui/index.ts", - "backend/pkg/extensionapi/v1/account_edit.go", - "backend/pkg/extensionapi/v1/resources.go", - "backend/pkg/extensionapi/v1/rpc.go", - "backend/pkg/extensionapi/v1/rpc_test.go", - "deploy/tests/cindy-rollout-defaults-test.sh", - "deploy/tests/production-deploy-workflow-test.sh", - "deploy/tests/test_verify_business_system_prompt_bundle.py", - "docs/PLUGIN_DEVELOPMENT.md", - "docs/channel-monitor-v2-safe-defaults.md", - "frontend/src/__tests__/fixtures/accountEdit.ts", - "frontend/src/api/__tests__/admin.accounts.editContext.spec.ts", - "frontend/src/api/admin/__tests__/accountJobs.spec.ts", - "frontend/src/api/admin/__tests__/systemPrompts.spec.ts", - "frontend/src/api/admin/accountViewClient.ts", - "frontend/src/api/admin/cnProviders.ts", - "frontend/src/api/admin/grok.ts", - "frontend/src/api/admin/pluginDispatch.ts", - "frontend/src/api/admin/plugins.ts", - "frontend/src/api/admin/scheduledTests.ts", - "frontend/src/api/admin/systemPrompts.ts", - "frontend/src/components/account/AccountTestModal.vue", - "frontend/src/components/account/AccountUsageCell.vue", - "frontend/src/components/account/BulkEditAccountModal.vue", - "frontend/src/components/account/CNProviderBalanceCell.vue", - "frontend/src/components/account/CNProviderQuotaCell.vue", - "frontend/src/components/account/CreateAccountModal.vue", - "frontend/src/components/account/EditAccountModal.vue", - "frontend/src/components/account/GrokQuotaProbeCell.vue", - "frontend/src/components/account/OllamaCloudUsageCell.vue", - "frontend/src/components/account/OpenAIQuotaResetCell.vue", - "frontend/src/components/account/SyncFromCrsModal.vue", - "frontend/src/components/account/TempUnschedStatusModal.vue", - "frontend/src/components/account/UpstreamBillingRateCell.vue", - "frontend/src/components/account/UsageProgressBar.vue", - "frontend/src/components/account/__tests__/AccountStatusIndicator.spec.ts", - "frontend/src/components/account/__tests__/AccountUsageCell.list.spec.ts", - "frontend/src/components/account/__tests__/AccountUsageCell.spec.ts", - "frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts", - "frontend/src/components/account/__tests__/CreateAccountModal.spec.ts", - "frontend/src/components/account/__tests__/EditAccountModal.grokMediaEligibility.spec.ts", - "frontend/src/components/account/__tests__/EditAccountModal.grokUpstream.spec.ts", - "frontend/src/components/account/__tests__/EditAccountModal.spec.ts", - "frontend/src/components/admin/account/AccountActionMenu.vue", - "frontend/src/components/admin/account/AccountBulkTaxonomyModal.vue", - "frontend/src/components/admin/account/AccountCardGrid.vue", - "frontend/src/components/admin/account/AccountCompactList.vue", - "frontend/src/components/admin/account/AccountDetailsDrawer.vue", - "frontend/src/components/admin/account/AccountFolderBar.vue", - "frontend/src/components/admin/account/AccountStatsModal.vue", - "frontend/src/components/admin/account/AccountTaxonomyManager.vue", - "frontend/src/components/admin/account/AccountTestModal.vue", - "frontend/src/components/admin/account/AccountViewModeSwitcher.vue", - "frontend/src/components/admin/account/BatchTestAccountModal.vue", - "frontend/src/components/admin/account/ImportDataModal.vue", - "frontend/src/components/admin/account/ReAuthAccountModal.vue", - "frontend/src/components/admin/account/ScheduledTestsPanel.vue", - "frontend/src/components/admin/account/__tests__/AccountActionMenu.spark_shadow.spec.ts", - "frontend/src/components/admin/account/__tests__/AccountUsageViews.spec.ts", - "frontend/src/components/admin/usage/UsageTable.vue", - "frontend/src/components/charts/__tests__/ModelDistributionChart.spec.ts", - "frontend/src/components/layout/AppHeader.vue", - "frontend/src/components/layout/AppSidebar.vue", - "frontend/src/components/layout/__tests__/AppSidebar.simple-mode.spec.ts", - "frontend/src/components/layout/__tests__/AppSidebar.spec.ts", - "frontend/src/components/payment/__tests__/SubscriptionPlanCard.spec.ts", - "frontend/src/components/plugins/AccountColumnDisplay.vue", - "frontend/src/components/plugins/AccountViewPage.vue", - "frontend/src/components/plugins/ExtensionDialog.vue", - "frontend/src/components/plugins/ExtensionDisplay.vue", - "frontend/src/components/plugins/ExtensionModal.vue", - "frontend/src/components/plugins/ExtensionPage.vue", - "frontend/src/components/plugins/ExtensionSlot.vue", - "frontend/src/components/plugins/ExtensionSurface.vue", - "frontend/src/components/plugins/ExtensionWidget.vue", - "frontend/src/components/plugins/PluginFrame.vue", - "frontend/src/components/plugins/__tests__/AccountViewPage.spec.ts", - "frontend/src/components/plugins/__tests__/CindyAccountControls.spec.ts", - "frontend/src/components/plugins/__tests__/ExtensionDialog.admission.spec.ts", - "frontend/src/components/plugins/__tests__/PluginFrame.precondition.spec.ts", - "frontend/src/components/plugins/__tests__/accountView.fixtures.ts", - "frontend/src/components/plugins/__tests__/accountView.spec.ts", - "frontend/src/components/plugins/__tests__/accountViewNative.spec.ts", - "frontend/src/components/plugins/__tests__/accountViewStepUp.spec.ts", - "frontend/src/components/plugins/__tests__/pluginViewDispatch.spec.ts", - "frontend/src/components/plugins/__tests__/resourceAvailability.spec.ts", - "frontend/src/components/plugins/accountView.ts", - "frontend/src/components/plugins/pluginContext.ts", - "frontend/src/components/plugins/pluginViewDispatch.ts", - "frontend/src/components/plugins/resourceClient.ts", - "frontend/src/components/plugins/useRetainedContribution.ts", - "frontend/src/composables/__tests__/useAccountEditProfile.spec.ts", - "frontend/src/composables/useAccountEditProfile.ts", - "frontend/src/composables/useAccountViewContext.ts", - "frontend/src/features/account-jobs/__tests__/integrationSurface.spec.ts", - "frontend/src/features/cindy-balance-probe/__tests__/CindyBalanceProbeSummary.spec.ts", - "frontend/src/features/prompt-audit/__tests__/PromptAuditView.spec.ts", - "frontend/src/i18n/locales/en/admin/accounts.ts", - "frontend/src/i18n/locales/zh/admin/accounts.ts", - "frontend/src/router/index.ts", - "frontend/src/stores/accountJobs.ts", - "frontend/src/utils/__tests__/accountEditCodec.spec.ts", - "frontend/src/utils/accountEditCodec.ts", - "frontend/src/views/admin/AccountsView.vue", - "frontend/src/views/admin/CindyAccountsView.vue", - "frontend/src/views/admin/SystemPromptsView.vue", - "frontend/src/views/admin/__tests__/AccountTasksView.spec.ts", - "frontend/src/views/admin/__tests__/AccountsView.console.spec.ts", - "frontend/src/views/admin/__tests__/AccountsView.lite.spec.ts", - "frontend/src/views/admin/__tests__/GroupsView.columnSettings.spec.ts", - "frontend/src/views/admin/__tests__/GroupsView.duplicate.spec.ts", - "frontend/src/views/admin/__tests__/systemPromptsIntegrationSurface.spec.ts", - "frontend/src/views/auth/WechatCallbackView.vue", - "frontend/src/views/auth/WechatPaymentCallbackView.vue", - "frontend/src/views/public/LegalDocumentView.vue", - "frontend/src/views/setup/SetupWizardView.vue", - "frontend/src/views/user/BatchImageGuideView.vue", - "frontend/src/views/user/ChannelStatusV2View.vue", - "frontend/src/views/user/CustomPageView.vue", - "frontend/src/views/user/ImageStudioView.vue", - "frontend/src/views/user/KeysView.vue", - "frontend/src/views/user/PaymentQRCodeView.vue", - "frontend/src/views/user/PaymentView.vue", - "frontend/src/views/user/RedeemView.vue", - "plugins/account-tools/ui/assets/app.js", - "plugins/account-tools/ui/assets/styles.css", - "plugins/account-tools/ui/src/api.ts", - "plugins/account-tools/ui/src/locales/en-accounts.ts", - "plugins/account-tools/ui/src/locales/en-common.ts", - "plugins/account-tools/ui/src/locales/zh-accounts.ts", - "plugins/account-tools/ui/src/locales/zh-common.ts", - "plugins/admin-observability/scripts/check-chart-colors.py", - "plugins/admin-observability/scripts/check-theme.py", - "plugins/admin-observability/scripts/check-ui.py", - "plugins/admin-observability/ui/assets/app.js", - "plugins/admin-observability/ui/assets/fonts/NOTICE.md", - "plugins/admin-observability/ui/assets/styles.css", - "plugins/admin-observability/ui/assets/theme.css", - "plugins/admin-observability/ui/index.html", - "plugins/admin-observability/ui/src/locales/en.ts", - "plugins/admin-observability/ui/src/locales/zh.ts", - "plugins/cindy-provider/manifest.source.json", - "plugins/cindy-provider/ui/src/App.vue", - "plugins/cindy-provider/ui/src/CindyAccountControls.vue", - "plugins/cindy-provider/ui/src/CindyCleanupDialog.vue", - "plugins/cindy-provider/ui/src/api.ts", - "plugins/cindy-provider/ui/src/locales/en.ts", - "plugins/cindy-provider/ui/src/locales/zh.ts", - "plugins/prompt-skills/registry/seed/manifest.json", - "plugins/prompt-skills/scripts/check-ui.py", - "plugins/prompt-skills/ui/assets/app.js", - "plugins/prompt-skills/ui/assets/styles.css", - "plugins/prompt-skills/ui/index.html", - "tools/sync_modelgang_remote_skill_seed.ps1", - "tools/verify_business_system_prompt_bundle.py" - ], - "role_counts": { - "asset": 6, - "bundled-source": 458, - "dependency-lock": 9, - "documentation": 28, - "generated": 68, - "source": 1092, - "test-or-fixture": 818 - }, - "owner_counts": { - "operations": 45, - "documentation-and-history": 26, - "mixed-requires-review": 1105, - "core-extension-and-job-host": 259, - "core-data-and-migrations": 21, - "cindy-provider": 207, - "image-tools": 45, - "account-tools": 81, - "codex-runtime": 44, - "prompt-skills": 555, - "core-quota-and-protocol": 22, - "admin-observability": 50, - "model-policy": 19 - }, - "entries": [ - { - "path": ".dockerignore", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "08292d37184c724ed98b0e71dfe47ebd6c1c4ea57f587552c7bd8aa0e06fb4f5", - "review_fingerprint": "08292d37184c724ed98b0e71dfe47ebd6c1c4ea57f587552c7bd8aa0e06fb4f5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "排除 Git/env/node_modules、插件目录内 key/packages/exe 和 compiled UI;仅七个源模块允许进入context。deploy/plugin-bundle/current 下正式包不被这些 /plugins/** 排除规则误删,供 release COPY 原样使用。", - "evidence": [ - "explicit seven module exceptions", - "/plugins/**/*.key/.s2plugin/.exe exclusions", - "deploy bundle remains eligible", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": ".downstream/README.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "edd8c6053acb5b21436cbb5b1a70676eb4777e571f3cdfbed3af46f2e8d94b19", - "review_fingerprint": "edd8c6053acb5b21436cbb5b1a70676eb4777e571f3cdfbed3af46f2e8d94b19", - "review_status": "pending" - }, - { - "path": ".downstream/cindy-catalog-refresh-20260905.json", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "4cb5cde792d4faec848d801a31c361af52841de9ab107c6eb515b414306a025a", - "review_fingerprint": "4cb5cde792d4faec848d801a31c361af52841de9ab107c6eb515b414306a025a", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "2026-09-05 的 Cindy 模型目录刷新探测快照:记录 observedAt、catalogSha256(9f27de4e…)、catalogCount=15、accountsUsed=1、nativeRequests=8、metadataSource=makecindy/cindy@81e383b5 与 probeEvidence 日志文件名,并列出 4 个模型(gemini-3.8-flash、muse-spark-1.3、gpt-6-astra、hy4-preview)在 responses/search/messages 三条通道的 HTTP 状态与 verified/metadataComplete/public 标记。上游 aea725f 无此路径(ls-tree 为空),整文件即下游增量;仓库内无代码按文件名引用它,属纯证据留档。静态阅读,未执行探测、未核对 sha 或日志。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Content anchor: 1243 bytes, single JSON object with keys observedAt/catalogSha256/catalogCount/accountsUsed/nativeRequests/retries/accountSwitches/metadataSource/probeEvidence/models[4]; gpt-6-astra is the only public=true entry (messagesStatus 400), hy4-preview has responsesSearchStatus 0.", - "Delta anchor: git ls-tree aea725f -- prints nothing, so the whole file is downstream-new; rg --no-config 'cindy-catalog-refresh' finds no code or doc referencing this filename; of its field names only 'accountSwitches' recurs in frontend/src/i18n/locales/{en,zh}/admin/ops.ts as a UI label, no parser of this file exists.", - "Not claimed: no verification of the recorded catalog sha256, probe log or metadataSource commit; no production behavior edit or test execution." - ] - }, - { - "path": ".downstream/cindy-catalog-refresh-20260911.json", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "cb4c957129ff60b6107339036e9003768c8bc099c51adecba4d5bce7203d835f", - "review_fingerprint": "cb4c957129ff60b6107339036e9003768c8bc099c51adecba4d5bce7203d835f", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "2026-09-11 的 Cindy 目录刷新探测快照,与 0905 快照同构但字段更少:catalogSha256(38045af0…)、catalogCount=17、nativeRequests=0、metadataSource=makecindy/cindy@2128cd45、probeEvidence 日志名,以及 3 个新模型(deepseek-flash、gpt-image-2.5-flare、gpt-image-2.5-sunburst)全部 verified=false/public=false,且不再携带 responsesSearchStatus/messagesStatus 状态码。上游无此路径,整文件为下游新增的证据留档,无代码引用。静态阅读,未执行探测或核对 sha。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Content anchor: 903 bytes; models[3] each carry only responsesVerified/searchVerified/messagesVerified/metadataComplete/public (all false), unlike the 0905 snapshot which also has HTTP status fields; nativeRequests=0 while accountsUsed=1.", - "Delta anchor: git ls-tree aea725f -- prints nothing (downstream-new); rg --no-config 'cindy-catalog-refresh' returns no referencing code, so the file is an evidence artifact rather than runtime input.", - "Not claimed: no verification of the recorded catalog sha256 or probe log; no production behavior edit or test execution." - ] - }, - { - "path": ".downstream/coverage-v0.2.7.json", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": null, - "review_fingerprint": "170d2291e9231ef547571507cccbaafc2e5dc5a52e67441071b68f89f43c8982", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "operations", - "reason": "Derived path, digest and verdict inventory; this structural check does not review the listed source files.", - "evidence": [ - "node .downstream/refresh-coverage.mjs --check" - ] - }, - { - "path": ".downstream/coverage-v0.2.7.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "cb6d534e090dcaaa710ae08455ae0426e4b1cf4def9e771410ce3e02aa139d4c", - "review_fingerprint": "cb6d534e090dcaaa710ae08455ae0426e4b1cf4def9e771410ce3e02aa139d4c", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "The handover distinguishes source classification from completed review and source provenance from semantics; documented check/import/require-complete behavior matches the current tool.", - "evidence": [ - "static correspondence with refresh-coverage.mjs; no service tests run for documentation" - ] - }, - { - "path": ".downstream/implementation-v0.2.7.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "761e38d7e67087536262a5ad0f15a8e8d5550aa17ccb0289a261ed6307869070", - "review_fingerprint": "761e38d7e67087536262a5ad0f15a8e8d5550aa17ccb0289a261ed6307869070", - "review_status": "pending" - }, - { - "path": ".downstream/refresh-coverage.mjs", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "ccecf776310182a061fcbcf05912879100d3c270ee9cdf483df5ad476142e55c", - "review_fingerprint": "ccecf776310182a061fcbcf05912879100d3c270ee9cdf483df5ad476142e55c", - "review_status": "pending" - }, - { - "path": ".downstream/refresh-coverage.test.mjs", - "candidate_owner": "documentation-and-history", - "role": "source", - "present": true, - "content_sha256": "cd86c85b17cfa69a471ea00987b03c7c9c5ededd940ddfadbdbe8148724587b0", - "review_fingerprint": "cd86c85b17cfa69a471ea00987b03c7c9c5ededd940ddfadbdbe8148724587b0", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "An isolated Git repository exercises review import, invalid claims with atomic non-write, source change invalidation and the require-complete gate. Its cleanup is limited to its own validated mkdtemp path.", - "evidence": [ - "node --test .downstream/refresh-coverage.test.mjs passed" - ] - }, - { - "path": ".downstream/upstream-0.2.0-overlap-review.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "3688bb9304342459a3aabd58de2105aa55f77cab637245cc14c1835892aa842c", - "review_fingerprint": "3688bb9304342459a3aabd58de2105aa55f77cab637245cc14c1835892aa842c", - "review_status": "pending" - }, - { - "path": ".downstream/upstream-base", - "candidate_owner": "documentation-and-history", - "role": "source", - "present": true, - "content_sha256": "52a3f5e5d8f8f97eb22767703aa81041e748c1e22297903c8f82c178cee68247", - "review_fingerprint": "52a3f5e5d8f8f97eb22767703aa81041e748c1e22297903c8f82c178cee68247", - "review_status": "pending" - }, - { - "path": ".downstream/upstream-review-v0.2.1.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "4bccf78935856357f49fc7bbea93807d2fe051f6bba232f922d97fbd0e691390", - "review_fingerprint": "4bccf78935856357f49fc7bbea93807d2fe051f6bba232f922d97fbd0e691390", - "review_status": "pending" - }, - { - "path": ".downstream/upstream-review-v0.2.5.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "4fb6834fe5fa4c236390be1d8132a4eef21de5493825714412a248960d887610", - "review_fingerprint": "4fb6834fe5fa4c236390be1d8132a4eef21de5493825714412a248960d887610", - "review_status": "pending" - }, - { - "path": ".downstream/upstream-review-v0.2.6.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "8f47ec184e0142212c72565b9e11cb9fd5957ae32a3a1783d20bf7dc7ef1fe39", - "review_fingerprint": "8f47ec184e0142212c72565b9e11cb9fd5957ae32a3a1783d20bf7dc7ef1fe39", - "review_status": "pending" - }, - { - "path": ".downstream/upstream-risk.json", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "806466a27fa30413b39ae72824ad16c6f06d1f87261ef41d6a9e9294aea7ba64", - "review_fingerprint": "806466a27fa30413b39ae72824ad16c6f06d1f87261ef41d6a9e9294aea7ba64", - "review_status": "pending" - }, - { - "path": ".gitattributes", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "8cc7df9f5eae47fa5ee5b25da81f98d383aef28888b1557fe1d6aee4364c65ee", - "review_fingerprint": "8cc7df9f5eae47fa5ee5b25da81f98d383aef28888b1557fe1d6aee4364c65ee", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Cross-platform text attributes pin LF for signed resources, review fingerprints, SQL and Go/TS/Vue/scripts. Embedded prompt and extensionless/Unicode seed files have explicit stable-byte rules; -whitespace is limited to approved seed source and does not suppress semantic checks or turn binary fonts into text.", - "evidence": [ - "Complete attribute file and upstream diff read. No renormalization or unrelated files rewritten this review.", - "artifacts/evidence/v027-lifecycle-wiring-review.json" - ] - }, - { - "path": ".github/scripts/initialize_plugin_publisher.go", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "2d8fc04a65fdaf6c444b511fdd65df6e3c80e42770906b4949a7b240a50eea39", - "review_fingerprint": "2d8fc04a65fdaf6c444b511fdd65df6e3c80e42770906b4949a7b240a50eea39", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "只查询 secret 名称 metadata;完整分页和总量一致性检查防止缺页误判。已有 public identity 与 Secret 的保护保留,private 通过 stdin 给既有 gh、不打印,退出清空 private/encoded bytes。测试不调用 run/main 或生成/写 key。注释明确并发 initializer 不受原子 create-only 保障。", - "evidence": [ - "publisherSecretExists full inventory", - "run refuses existing metadata/secret replacement", - "github stderr suppression/stdin", - "v027-astra-release-supply-chain-review.json:T-003", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": ".github/scripts/initialize_plugin_publisher_test.go", - "candidate_owner": "operations", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d2ece4236dec377cc24cd3cbb970a1e7cfe1e8dfa7a1beff0a426551347f6202", - "review_fingerprint": "d2ece4236dec377cc24cd3cbb970a1e7cfe1e8dfa7a1beff0a426551347f6202", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "注入 query 函数只允许 api metadata 输入;覆盖后页目标 Secret、API 失败、不完整末页、总数变化、重复名称、缺失 shape 及完整空列表。未调用真实 gh 或密钥生成。", - "evidence": [ - "TestPublisherSecretInventoryFindsLaterPageWithoutInitializing", - "TestPublisherSecretInventoryIncompleteOrFailedPageIsNotAbsence", - "TestPublisherSecretInventoryRequiresExplicitCompleteMetadata", - "v027-astra-release-supply-chain-review.json:T-003", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": ".github/scripts/release_preflight.py", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "29758dc58fe190f1621115e6f1db46f7a1176864ca7373ec5a091b96bd47225b", - "review_fingerprint": "29758dc58fe190f1621115e6f1db46f7a1176864ca7373ec5a091b96bd47225b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "固定 HTExplicit/sub2api 和 GHCR image,不接受任意 repo/host/command。GitHub CLI 仅显式 GET,release inventory 全分页并拒绝重复/不完整;tag 精确匹配、注释 tag 有界解引用。GHCR 只用既有 job token,拒绝 redirects/未知状态,只有明确 MANIFEST_UNKNOWN 404 才是缺失。公开前校验 inventory 对应的 local lock/包 SHA、唯一 draft 的 assets name/count/size/digest,以及 host image digest;最后读取 tag/source。输出固定粗错误,不打印 token 或原错误体。没有任何 publish/sign/delete 方法。", - "evidence": [ - "github_json/list_releases/tag_commit", - "NoRedirect/http_get/registry_manifest", - "local_assets/check", - "v027-astra-release-supply-chain-review.json:T-001", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": ".github/scripts/test_agent_protocol.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "f6629260c6f70e772de24da4230b4e58f144a2d122887c93c6951867f2b22700", - "review_fingerprint": "f6629260c6f70e772de24da4230b4e58f144a2d122887c93c6951867f2b22700", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "全文20行复核:固定repo相对路径创建缺失embed夹具,现有3个Go命令保持,只扩pkg/service选择器命中9个新增方法;未另开重复suite、联网或改必需CI。bash -n及从3个实际fixture提取函数名逐一匹配选择器均通过,未执行整份CI脚本或重复已绿业务用例。", - "evidence": [ - "artifacts/evidence/v027-protocol-completion-integration-review.json#verification", - "Actual static selector/format/hash check chunk 1f55cf, exit0. Parent owns this CI change; subagent report deliberately did not claim it." - ] - }, - { - "path": ".github/scripts/test_first_party_plugins.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "a032b8dba712b37f9a7ed7e84c1e4289bfcc4908ba2307ac61eff85d7e50e8e3", - "review_fingerprint": "a032b8dba712b37f9a7ed7e84c1e4289bfcc4908ba2307ac61eff85d7e50e8e3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "在私有 mktemp 目录生成测试 key,key-id 为 codexrip-plugins-test;先构建独立 binaries,传测试 public key/bundle 路径给具名进程契约测试。它只在正常 Verify 中运行,release workflow 不调用它,未复用或接触正式 signing Secret。", - "evidence": [ - "generate-key temporary path", - "-key-id codexrip-plugins-test", - "eight named process/bundle tests", - "downstream-verify invocation", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": ".github/scripts/test_model_context_capacity.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "e5d56b5f1359a4d402236b235c8944561562c5b69f758182e1ebbfc095cabcad", - "review_fingerprint": "e5d56b5f1359a4d402236b235c8944561562c5b69f758182e1ebbfc095cabcad", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "下游新增的离线 Go 测试门禁脚本:定位到 backend 后以 -tags unit 对 internal/service、repository、handler、handler/admin 与 cmd/server 五个包按正则 Test.*(ModelContext|ContextCapacit|GroupModelCapacity|ConvertOpenAIModelListLiveCapacity|CodexCapacityProjection|SyncUpstreamModelCatalog.*Capacity|RunCodexContextContractVerification) 运行模型上下文容量契约测试,上游无此文件。已用 rg 核对该正则命中 69 个真实测试函数(66 个在 internal/*,3 个在 cmd/server),脚本本身不含凭据、不访问网络,由 downstream-verify.yml 调用,属 operations 的 CI 机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L1-L11 whole file is downstream delta (git ls-tree aea725f prints nothing): set -euo pipefail, repo_root via BASH_SOURCE, cd \"$repo_root/backend\", one go test -p=1 -tags unit -count=1 invocation with an unanchored -run regex.", - "Consumer: .github/workflows/downstream-verify.yml L54 'bash .github/scripts/test_model_context_capacity.sh'. rg over backend/ shows the -run regex matches 69 existing func Test* (e.g. TestGroupModelCapacity*, TestCodexCapacityProjection*, TestModelContextCapacityContract*, TestConvertOpenAIModelListLiveCapacitySurvivesSparseConversion), so the gate is not a no-op.", - "internal/service TestMain (cindy_rollout_testmain_test.go) only re-execs the suite with Cindy feature env vars; no network path is introduced by this gate.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/scripts/test_reasoning_replay.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "1815d100520726ee78ba4485f30a7d11aabafee755479d38f1f51464e2c33cf5", - "review_fingerprint": "1815d100520726ee78ba4485f30a7d11aabafee755479d38f1f51464e2c33cf5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "下游新增的推理回放/恢复契约门禁:第一条 go -C backend test -tags unit 在 apicompat、repository、service、handler/admin 运行 Test(OpenAIChatReasoning|OpenAIReasoning|OpenAIHTTPTerminal|GatewayCacheReasoningState|SchedulerCacheReasoningPolicy|ResponsesReasoningConfiguration);第二条以 reasoning_fidelity,reasoning_replay_diagnostic 两个 build tag 只运行锚定的 ^TestReasoningReplayDiagnostic(Control|ChatParse)$。已核对两个诊断测试位于 reasoning_replay_diagnostic_{control,parse}_test.go 且带相同 build 约束;同 tag 编译进来的 *_live_test.go 函数名不匹配锚定正则且内部再以 SUB2API_*_LIVE=1 环境变量门控,因此注释所称“不消费账号凭据或模型请求”成立。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L1-L10 whole file is downstream delta: cd to repo root, two go -C backend test invocations, -p=1 -count=1, second one restricted by build tags and an anchored -run.", - "rg: every name in the first -run alternation resolves to test files (openai_chat_reasoning_replay_test.go, openai_http_terminal_boundary_test.go, gateway_cache_reasoning_state_test.go, scheduler_cache_reasoning_policy_test.go, apicompat/responses_reasoning_test.go, admin/account_reasoning_policy_test.go). TestReasoningReplayDiagnosticControl (L81) and ...ChatParse (L551) carry '//go:build reasoning_fidelity && reasoning_replay_diagnostic'.", - "Live variants compiled under the same tags (reasoning_replay_diagnostic_live_test.go, reasoning_fidelity_live_test.go) are excluded by the anchored -run and additionally gated by os.Getenv(SUB2API_REASONING_REPLAY_LIVE)!=1; consumer is downstream-verify.yml L52.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/scripts/test_release_preflight.py", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "d762854dd0199950035ea249d4d877418278b9d41bbc2b2090c025469fefd2c6", - "review_fingerprint": "d762854dd0199950035ea249d4d877418278b9d41bbc2b2090c025469fefd2c6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "九个 metadata 方法使用 fake GitHub/GHCR;五个 workflow 方法检查 pin、build/push 顺序、draft 发布、私钥/GH_TOKEN scope,并在私有临时 cwd 用 git-function mock 验证临时 auth。包字节仅合成 fixture,不是签名或 Docker 集成。", - "evidence": [ - "ReleaseMetadataTests", - "ReleaseWorkflowContracts", - "v027-astra-release-supply-chain-review.json:T-001", - "v027-astra-release-supply-chain-review.json:T-002", - "v027-astra-release-supply-chain-review.json:T-004", - "v027-astra-release-supply-chain-review.json:T-006", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": ".github/scripts/test_upstream_automation_contract.py", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "09344384f08773d421301905cdf3468d8605e1a34d08375e999e4d5a38c2c112", - "review_fingerprint": "09344384f08773d421301905cdf3468d8605e1a34d08375e999e4d5a38c2c112", - "review_status": "pending" - }, - { - "path": ".github/scripts/test_upstream_risk.py", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "ae883e9a105b7dd00a25f6c75100344b8258e04e3a20a3c2a89033e2109e9b74", - "review_fingerprint": "ae883e9a105b7dd00a25f6c75100344b8258e04e3a20a3c2a89033e2109e9b74", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "upstream_risk.py 的单元测试:证明零重叠且无关键路径判 safe、任意重叠判 review_required、15 类受保护路径族(workflows、Dockerfile、deploy、go.mod、pnpm-lock、migrations、ent、repository、securityaudit、billing、openai_ws、plugin_update、extensionapi、pluginapi、plugins/manifest)均 is_critical,并在 gettempdir 内临时 git 仓库中用中文文件名 .github/workflows/发布.yml 证明 analyze 的 -z/NUL 路径处理不会把 unicode 工作流路径漏判为 safe。测试只 git init 临时目录,不触网。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L12-L21 classify() contracts; L23-L42 subTest over 15 critical paths mirroring the 6 CRITICAL_PATHS regexes of upstream_risk.py L13-L23.", - "L44-L63 real-git fixture: TemporaryDirectory under gettempdir (asserted L47), two commits tagged v1.0.0/v1.1.0, analyze(repo,'v1.0.0','v1.1.0','v1.0.0') must return critical_files==[workflow] and review_required.", - "Consumers: downstream-verify.yml L60, upstream-sync.yml L43, upstream-risk-gate.yml L65 (trusted checkout). Imports analyze/classify/is_critical from upstream_risk.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/scripts/upstream_promote.py", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "f868309a81bf70984b536d37a631322cd7eba8971531468364ff4acfc0dc456d", - "review_fingerprint": "f868309a81bf70984b536d37a631322cd7eba8971531468364ff4acfc0dc456d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "把一个已评审的上游同步 PR 推进到不可变发布与受保护部署的脚本。validate_candidate 要求 PR 属于 HTExplicit/sub2api 且目标 main、分支名 sync/upstream-X 与 .downstream/upstream-base 一致、无 merge_conflicts、safe 分类不得含重叠/关键文件、review_required 必须带 upstream-reviewed 标签;promote 拉取官方标签并用 analyze 重算风险清单逐键比对,等待 10 个 REQUIRED_CHECKS 全部 success(2h 上限、300/600s 退避),以 --match-head-commit 合并,创建或校验 -codexrip.1 标签,ensure_release 只调度 downstream-release.yml 一次并校验 release body 的 Source/Image 行,最后 dispatch production-deploy.yml(deploy-preserve, DEPLOY)。脚本会排队生产部署,但只经 GitHub 工作流分发且仍受 production 环境审批;command() 出错只回显程序名与返回码不回显 stderr/参数,子进程全部为列表参数无 shell。观察:L157 重算 analyze 时 downstream_commit 取自 PR 自带的 manifest,未与 origin/main 或候选合并提交的第一父提交绑定(findings,低)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L37-L55 validate_candidate; L64-L91 require_checks (REQUIRED_CHECKS L17-L21 = shell,test,frontend,golangci-lint,Downstream backend/frontend,Candidate OCI image,backend-security,frontend-security,Upstream risk gate); L94-L109 release_ready parses 'Source: `<40hex>`' and exactly one 'Image: `ghcr.io/htexplicit/sub2api:@sha256:<64hex>`'.", - "L139-L196 promote: git fetch origin head main; manifest from :.downstream/upstream-risk.json; L153-L156 fetches Wei-Shaw tags and checks merge-base --is-ancestor; L161-L165 re-reads PR and rejects if head changed; L169-L170 gh pr merge --merge --match-head-commit; L177-L184 tag reuse only if it points at the merge commit; L187-L195 production-deploy dispatch de-duplicated by run title 'Deploy (preserve)'.", - "Consumers: upstream-promote.yml L40 (workflow_dispatch, confirmation=PROMOTE, only HTExplicit/sub2api main); contract tests in test_upstream_automation_contract.py L139-L260. Finding: L157 analyze(..., manifest['downstream_commit']) is self-referential (see findings).", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/scripts/upstream_risk.py", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "099dfdf0cb40e89d9742f48a789ca878ba1322fb7f12cad92e4a4aff71dd2ed2", - "review_fingerprint": "099dfdf0cb40e89d9742f48a789ca878ba1322fb7f12cad92e4a4aff71dd2ed2", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "上游稳定版合并风险分类器。CRITICAL_PATHS 六组正则覆盖 .github/workflows|actions、Dockerfile/docker-compose/deploy/.dockerignore、backend/go.mod|sum 与 frontend/package.json|pnpm-lock、backend/migrations|ent、plugins/ 与 backend/pkg/pluginapi|extensionapi、以及 backend/internal 下 auth/securityaudit/repository/server/middleware 和 service/billing|pricing|ratelimit|account_scheduler|gateway|openai_|plugin_|api_key_auth;classify 仅在零重叠且零关键文件时给 safe,否则 review_required;analyze 用 git diff --name-only -z(NUL 分隔、surrogateescape)取 base..tag 与 base..downstream 文件集合;main 以 v\\d+.\\d+.\\d+ 全匹配校验两个标签,写 JSON 并追加 GITHUB_OUTPUT。子进程列表参数、无 shell、不触网。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L13-L23 CRITICAL_PATHS; L39-L40 is_critical; L43-L59 classify returns risk_class + sorted file lists + 4 counts; L62-L74 analyze adds schema/upstream_base/upstream_tag/downstream_commit/merge_conflicts=[].", - "L77-L98 argparse main: --base/--tag validated by re.fullmatch(r'v[0-9]+\\.[0-9]+\\.[0-9]+'), --output parent mkdir, optional --github-output appends risk_class/overlap_file_count/critical_file_count.", - "Consumers: upstream-sync.yml L82-L84 (--repo . default downstream ref HEAD=main), upstream-risk-gate.yml L73-L75 (trusted copy, --downstream-ref from candidate manifest), upstream_promote.py L13/L157 (analyze). Tests: test_upstream_risk.py.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/workflows/backend-ci.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "70931c35a6ba720db922db2025a7ca0d23e00496b0ece6ad794d3164792f33f7", - "review_fingerprint": "70931c35a6ba720db922db2025a7ca0d23e00496b0ece6ad794d3164792f33f7", - "review_status": "pending" - }, - { - "path": ".github/workflows/downstream-release.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "bf69f1d91401aa24b8abb45b8e6ea54fe79c97f9687c0223c59db282e11360f4", - "review_fingerprint": "bf69f1d91401aa24b8abb45b8e6ea54fe79c97f9687c0223c59db282e11360f4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "read-only verify 固定 SHA 后 publisher 只 checkout 该 SHA;签名、OCI revision/COMMIT、notes 共用 source。签名一次的 bundle 同目录进入 release-stage image 与 GitHub assets。build/load 完成后才登录 registry,在 push 前拒绝既有/不确定版本;引用确定 push digest 进行 attest、draft、资产完整性检查后公开。release 没有重跑业务/前端/race/迁移测试,也没有新增生产验收/backup/canary。", - "evidence": [ - "verify contents:read", - "publish ref=needs.verify.outputs.source_sha", - "Sign bundle step env", - "push:false/load:true then guarded docker push", - "steps.push.outputs.digest", - "explicit draft lifecycle", - "v027-astra-release-supply-chain-review.json:T-001", - "v027-astra-release-supply-chain-review.json:T-002", - "v027-astra-release-supply-chain-review.json:T-004", - "v027-astra-release-supply-chain-review.json:T-006", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": ".github/workflows/downstream-verify.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "04dfd0623217d0059b55fb6a5ab8170e6328396a138297f37ebc2d69b864561b", - "review_fingerprint": "04dfd0623217d0059b55fb6a5ab8170e6328396a138297f37ebc2d69b864561b", - "review_status": "pending" - }, - { - "path": ".github/workflows/legacy-ghcr-cleanup.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "6c8df2f8c810271b2a0ee6a1240fe5a05e75f54f25f256af9071e89d663e1328", - "review_fingerprint": "6c8df2f8c810271b2a0ee6a1240fe5a05e75f54f25f256af9071e89d663e1328", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "一次性手工触发的 GHCR 包版本清理工作流:需 confirmation=DELETE_LEGACY_GHCR 且 ref 为 main(job if 与脚本内 L87 双重检查);用 gh api --paginate 拉取 HTExplicit/sub2api 容器包版本,对 3 个受保护标签(0.1.172-codexrip.10-12)与 7 个目标标签(codexrip.3-9)分别要求“恰好一个版本且该版本只带这一个标签”,目标版本 id 或 digest 与任一受保护版本重合即拒绝,目标数不为 7 也拒绝;删除后重新拉取核验目标标签消失、受保护版本 id|digest 未变。只用 github.token(packages:write),不涉及生产主机/SSH;jq 均以 --arg 传值。属已完成的一次性运维清理,再次运行会因 count!=1 而 fail-closed。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L4-L9 workflow_dispatch confirmation input; L11-L13 permissions contents:read packages:write; L21 job if github.ref==main && confirmation match; L87-L90 second in-script ref check.", - "L48-L85 helpers fetch_versions/find_tag_versions/require_single_tag_version (exactly one version, tags == [tag], numeric id, non-empty digest); L96-L121 protected/target validation with cross-check L110-L113 and count==7 L118; L123-L127 gh api --method DELETE per validated id; L129-L147 post-delete verification.", - "New downstream file (no upstream blob). Not referenced by any other workflow or script (rg over .github/ shows only the coverage manifests).", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/workflows/plugin-release.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "d847a6995ddd16b5611f39e3f1cc913969f076158f75db1d21d72a4f0105b14e", - "review_fingerprint": "d847a6995ddd16b5611f39e3f1cc913969f076158f75db1d21d72a4f0105b14e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "dispatch 输入经严格 tag/domain/version 校验;确切 tag SHA main 准入、host SHA 比较、唯一已 published host release、metadata 写前检查和 draft 公开屏障相连。私钥只在 Sign selected package step;程序和 UI 先构建。无 clobber/delete/强制换 tag,既有同 tag Release/draft 都拒绝;只有选定包和 lock 被上传。", - "evidence": [ - "qualified checkout and SHA outputs", - "per-step GH_TOKEN and transient git auth", - "before-sign/create/publish calls", - "explicit draft and verified release ID PATCH", - "v027-astra-release-supply-chain-review.json:T-002", - "v027-astra-release-supply-chain-review.json:T-004", - "v027-astra-release-supply-chain-review.json:T-006", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": ".github/workflows/production-deploy.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "35da7586925cc750cfa20392dc1e1a990fbabd6bce97bfb1f0371f82fd7b3865", - "review_fingerprint": "35da7586925cc750cfa20392dc1e1a990fbabd6bce97bfb1f0371f82fd7b3865", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "生产部署工作流(workflow_dispatch,operation ∈ deploy/deploy-preserve/reconcile-runtime/rollback)。resolve 作业仅 packages:read:校验 confirmation 字面值、标签格式 v*-codexrip.N、release 非 draft/prerelease、release 资产不含已移除的 Skill 资产、tag commit 是 origin/main 祖先、release body 恰有一行 Image 与一行 Source、镜像 digest 与 org.opencontainers.image.revision 等于 tag commit、cindy-platform-v1 标签按角色校验,rollback 还要求目标版本 sort -V 严格小于当前版本且两镜像不同。deploy 作业绑定 environment: production(需人工审批),把 VPS_DEPLOY_KEY/VPS_KNOWN_HOSTS 写入文件后以 BatchMode+StrictHostKeyChecking=yes+IdentitiesOnly 的单条 ssh 传递已正则白名单校验的 remote_command,最后 curl PUBLIC_HEALTH_URL。该文件按设计可触达生产 VPS,但所有输入经白名单校验、密钥不回显(printf 到文件、ssh-keygen -y 输出丢弃)、concurrency 组 production-sub2api 不取消进行中运行。仅静态阅读,未触发任何运行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L5-L69 inputs (operation choice, release_tag, expected_current_release_tag, confirmation, 5 Cindy flags, interrupt_business, resource_profile); L71-L77 permissions contents/packages read, concurrency production-sub2api cancel-in-progress:false.", - "L127-L188 resolve_release_image: validate_release_tag regex, gh release view state/assets/body, git merge-base --is-ancestor tag_commit origin/main, digest and revision label cross-checks via docker buildx imagetools inspect; L190-L195 version_strictly_less via LC_ALL=C sort -V; L197-L231 confirmation/operation matrix incl. preserve mode forcing INTERRUPT_BUSINESS=false and RESOURCE_PROFILE=preserve.", - "L265-L360 deploy job: environment production; L271-L282 key material only written to ~/.ssh files (never echoed); L299-L343 re-validation of every resolve output by regex before building remote_command; L344-L355 ssh -F /dev/null -o BatchMode=yes -o StrictHostKeyChecking=yes; L356-L360 curl health with output discarded. Dispatched by upstream_promote.py L194-L195, upstream-auto-deploy.yml L69-L72; text-asserted by test_upstream_automation_contract.py L54-L55 and deploy/tests/production-deploy-workflow-test.sh.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/workflows/release.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "e6db4ac1c4d6fbc0975de6be560b06e49a5e1420c6695e907a3696080f8bc0c9", - "review_fingerprint": "e6db4ac1c4d6fbc0975de6be560b06e49a5e1420c6695e907a3696080f8bc0c9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "上游 GoReleaser 发布工作流;下游仅在 update-version 与 build-frontend 两个作业增加 if: !contains(github.ref_name,'-codexrip.') && !contains(inputs.tag,'-codexrip.'),使 vX.Y.Z-codexrip.N 标签推送时这两个作业跳过,依赖它们的 release 与 sync-version-file 随之跳过,由 downstream-release.yml(on push tags v*.*.*-codexrip.*)接管下游不可变镜像发布,避免同一标签被上游流程二次发布或回写 VERSION。其余内容(DockerHub/GHCR 登录、GoReleaser、Telegram 通知、VERSION 同步提交)与上游一致。L228 把 tag message 用单引号内联进 shell 属上游既有写法,非下游改动。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +2 lines only, L31 and L56 job-level if guards; upstream blob abdfc9c8.", - "Skip chain verified: release needs [update-version, build-frontend] (L90) and sync-version-file needs release with result=='success' (L278-L279), so a codexrip tag makes the whole workflow a no-op; downstream-release.yml L12-L13 triggers on 'v*.*.*-codexrip.*' and L52 validates the same tag shape.", - "Rest of the file (L1-L30, L32-L55, L57-L308) read in full and matches upstream; no downstream secrets or hosts added. Upstream_promote.py REQUIRED_CHECKS does not depend on this workflow.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/workflows/security-scan.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "c6bc18d917d57a79396195322d2874150ad43b42718022beeafbe2d8118bc5e9", - "review_fingerprint": "c6bc18d917d57a79396195322d2874150ad43b42718022beeafbe2d8118bc5e9", - "review_status": "pending" - }, - { - "path": ".github/workflows/upstream-auto-deploy.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "8ed11ada9b67d61106ee4feda9470f37ea4854189670d3d884b98d5d69346da9", - "review_fingerprint": "8ed11ada9b67d61106ee4feda9470f37ea4854189670d3d884b98d5d69346da9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "下游新增:监听 “Downstream Release” 工作流成功完成,仅当 head_branch 为 v*-codexrip.1(自动链固定的 .1 标签)时进入;用 git init + fetch --depth=1 拉取该 release commit,读取其 .downstream/upstream-risk.json:review_required 直接 eligible=false 退出(不 dispatch 也不误报失败),safe 则再要求 overlap/critical 均为 0 且标签等于 upstream-base+\"-codexrip.1\";随后按运行标题 “Deploy (preserve)” 去重后 dispatch production-deploy.yml(deploy-preserve, DEPLOY),失败时创建/更新 upstream-automation-failed issue 而不重试。会排队生产部署但仍受 production 环境审批;标签经正则校验后才拼进 jq 程序,gh 写操作均带 --repo \"$GITHUB_REPOSITORY\"。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L3-L6 workflow_run on 'Downstream Release' completed; L21-L24 job if success && startsWith 'v' && endsWith '-codexrip.1'; L8-L11 permissions actions/issues write, contents read.", - "L36-L56 candidate validation: RELEASE_TAG regex ^v[0-9]+\\.[0-9]+\\.[0-9]+-codexrip\\.1$, jq -er .risk_class, review_required branch echoes eligible=false and exit 0 (asserted by test_upstream_automation_contract.py L93-L101), safe branch requires counts 0 and tag == upstream-base + '-codexrip.1'.", - "L58-L72 single dispatch guarded by gh run list displayTitle count == 0; L74-L90 failure issue without retry loop ('for attempt' absent, asserted L124-L125 of the contract test).", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/workflows/upstream-auto-release.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "53c15a8c8cbdf4e7d1e0c55e400a9b14f235e66d86f96bafe038a22b605d565b", - "review_fingerprint": "53c15a8c8cbdf4e7d1e0c55e400a9b14f235e66d86f96bafe038a22b605d565b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "下游新增:pull_request_target closed 且 merged、head.ref 以 sync/upstream- 开头、带 upstream-safe-candidate 标签时,仅 dispatch upstream-promote.yml(pr_number, confirmation=PROMOTE),让 upstream_promote.py 复用已合并 PR 走“打标签→发布→排队部署”;失败则创建/更新 upstream-automation-failed issue 且不循环重试。不检出任何代码,pull_request_target 下无不可信代码执行;声明的 contents: write 对本工作流的两条 gh 命令并非必需(仅需 actions/issues write),属权限偏宽而非缺口。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L3-L5 pull_request_target types [closed]; L18-L21 if merged && startsWith(head.ref,'sync/upstream-') && label upstream-safe-candidate; L7-L10 permissions actions/contents/issues write.", - "L27-L34 single step: PR_NUMBER regex ^[1-9][0-9]*$ then gh workflow run upstream-promote.yml --repo \"$GITHUB_REPOSITORY\" --ref main -f pr_number -f confirmation=PROMOTE; no checkout step anywhere in the file.", - "L36-L52 failure issue create/update mirrors upstream-auto-deploy.yml; label upstream-safe-candidate is applied by upstream-sync.yml L181 only for risk_class==safe.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/workflows/upstream-promote.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "ace4c8008207c244e65d170161d8e37c89a5cf5774839e5ef924a406f5ce7dd6", - "review_fingerprint": "ace4c8008207c244e65d170161d8e37c89a5cf5774839e5ef924a406f5ce7dd6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "下游新增的手工/自动共用入口:workflow_dispatch(pr_number, confirmation=PROMOTE),只在 HTExplicit/sub2api 的 main 上运行,checkout main(fetch-depth 0) 后执行 python3 .github/scripts/upstream_promote.py --pr。权限 contents/pull-requests/actions: write 与脚本的合并、建标签、dispatch 需求匹配;timeout-minutes 180 小于脚本内 require_checks(2h)+ensure_release(2h) 的理论上限,超时被杀后重跑可依赖脚本对已存在标签/发布/部署运行的幂等复用。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L3-L13 inputs pr_number/confirmation; L14-L17 permissions; L18-L20 concurrency upstream-reviewed-promotion cancel-in-progress:false; L23 if repository=='HTExplicit/sub2api' && ref==refs/heads/main.", - "L29-L32 pinned actions/checkout sha, ref main, fetch-depth 0; L37-L40 confirmation==PROMOTE and numeric PR regex before invoking the promoter.", - "Dispatched by upstream-sync.yml L193-L194 (safe + auto_promote) and upstream-auto-release.yml L33-L34; timeout budget note: script deadlines 7200s each (upstream_promote.py L65, L123).", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/workflows/upstream-risk-gate.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "3dbdc0fd6ed0647aca1db6ff2925c37be17042392da6531f6b95e06690769639", - "review_fingerprint": "3dbdc0fd6ed0647aca1db6ff2925c37be17042392da6531f6b95e06690769639", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "下游新增的 PR 风险门禁:pull_request_target(opened/synchronize/reopened/labeled/unlabeled) 或手工 dispatch;先用 gh api 锁定 PR head sha 等于事件 sha 且 head 仓库为本仓库,再把 main 检出到 trusted/、候选 sha 仅作为数据检出到 candidate/,只运行 trusted/ 下的 test_upstream_risk.py 与 upstream_risk.py;从候选 manifest 取 base/tag/downstream_commit(正则且拒绝符号链接),fetch 官方标签后重算并对 12 个键逐一 diff,safe 需 overlap/critical 为 0,否则必须已带 upstream-reviewed 标签。权限只读(contents/pull-requests: read)。观察:重算时的 --downstream-ref 取自候选 manifest 自身,未与 origin/main 或候选合并提交的第一父提交绑定(findings,低)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L10-L11 pull_request_target types; L13-L15 read-only permissions; L24 job if dispatch || startsWith(head.ref,'sync/upstream-'); L33-L41 head sha == EXPECTED_SHA and head repo == GITHUB_REPOSITORY.", - "L42-L55 two checkouts (trusted=main, candidate=exact sha as data); L65 test_upstream_risk.py from trusted; L66-L67 manifest must be a regular file; L68-L70 jq -er with regex selects; L71-L72 fetch Wei-Shaw tags; L73-L78 recompute with trusted upstream_risk.py and diff -u per key; L79-L86 merge_conflicts==[] and safe/reviewed enforcement.", - "Text-asserted by test_upstream_automation_contract.py L39-L44; dispatched by upstream-sync.yml L191. Finding: L70/L74 downstream_commit is read from the candidate manifest and fed back to the recomputation (see findings).", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".github/workflows/upstream-sync.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "fd5ba15a5bab7ade8996ad4724ba726786aba9e528fe86a372e36980799dbe5f", - "review_fingerprint": "fd5ba15a5bab7ade8996ad4724ba726786aba9e528fe86a372e36980799dbe5f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "下游新增的每小时上游稳定版同步:先运行两套 Python 契约测试,gh api 解析官方 releases/latest(或指定标签)且要求非 draft/prerelease、版本不低于 .downstream/upstream-base;fetch 官方 base/tag 两个标签后由 upstream_risk.py 生成 .downstream/upstream-risk.json;候选分支已存在则不覆盖并开 issue(保留人工解决),合并冲突则 abort 并上传 /tmp/upstream-conflict.{md,json};无冲突时提交 upstream-base+manifest 推送 sync/upstream-X,创建/更新 PR 并按风险贴 upstream-safe-candidate(开启 --auto --merge)或 upstream-review-required,显式 dispatch backend-ci/security-scan/downstream-verify/upstream-risk-gate,safe 且 auto_promote 时再 dispatch upstream-promote。内联进 shell 的 ${{ }} 值均先经正则校验;L123-L124 的 --force-with-lease 分支在 L87-L95 提前 exit 后不可达(契约测试 L31 仍断言其文本存在),属无害死代码。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L4-L17 hourly cron '17 * * * *' + dispatch inputs upstream_tag/auto_promote; L19-L23 permissions actions/contents/pull-requests/issues write; L41-L44 runs test_upstream_risk.py and test_upstream_automation_contract.py first.", - "L46-L66 stable-release resolution (jq select draft==false && prerelease==false, tag regex, sort -V non-regression); L68-L129 candidate branch: existing branch => conflict report without overwrite (L86-L96), git merge --no-ff --no-commit with abort + conflicted path list (L98-L118), commit of .downstream/upstream-base + upstream-risk.json and push (L120-L127).", - "L146-L197 PR create/edit with labels, gh pr merge --auto --merge only for safe, explicit dispatch of backend-ci/security-scan/downstream-verify/upstream-risk-gate and conditional upstream-promote; every gh mutation carries --repo \"$GITHUB_REPOSITORY\" (verified by contract test L131-L136). Dead branch: L123 'if [[ -n \"$old_remote\" ]]' cannot be true after L87 exit.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": ".gitignore", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "4c2c7da4f3884389387b537b4775741d6eac912ebf576582cac70336def6701c", - "review_fingerprint": "4c2c7da4f3884389387b537b4775741d6eac912ebf576582cac70336def6701c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "下游三处改动:(1) 在全局按名字忽略 scripts 目录之后放行 .github/scripts/ 及其中 *.py(两个 .sh 门禁脚本文件名不匹配 scripts 规则,git check-ignore --no-index 也未报忽略);(2) 新增 __pycache__/ 与 *.py[cod];(3) 把上游整目录忽略 /plugins/ 改为 /plugins/* 加逐项放行:bundle.source.json、七个第一方插件目录及各自 scripts/check-ui.py(admin-observability 为 check-theme.py)、prompt-skills seed tree 的 scripts/**,同时忽略插件 dist/node_modules/ui/compiled/*.s2plugin 产物、任何 /plugins/**/*.key 私钥和 /deploy/plugin-bundle/current/ 安装产物——这是 v0.2.7 插件源码入库的前提。放行项 /plugins/model-catalog/ 在磁盘与索引中均不存在,属无害的过期条目。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +36/-2 at L125-L126 (!.github/scripts/, !.github/scripts/*.py), L155-L156 (__pycache__/, *.py[cod]), L163-L194 (plugins whitelist replacing '/plugins/'); upstream blob 5dafefb3. Whole 194-line file read.", - "git check-ignore -v --no-index on slice paths returned only negation rules (!.github/scripts/*.py, !deploy/tests/**, !docs/PLUGIN_DEVELOPMENT.md, !docs/channel-monitor-v2-safe-defaults.md, !/plugins/codex-runtime/scripts/check-ui.py, !/plugins/bundle.source.json) and nothing for the .sh gate scripts or deploy/plugin-bundle/README.md, i.e. none of them is ignored.", - "ls plugins/ shows account-tools, admin-observability, cindy-provider, codex-runtime, image-tools, model-policy, prompt-skills, bundle.source.json; git ls-files plugins/model-catalog is empty (stale whitelist line L181). L193 '/plugins/**/*.key' keeps signing keys out of the tree.", - "Static read only; no git write or index change." - ] - }, - { - "path": ".superpowers/sdd/cindy-group-account-ops-v180/progress.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "c5ccc7c65a1125f5e200fd43f0e4cffd57ee34f3b9cc0a848267792849d6f5f0", - "review_fingerprint": "c5ccc7c65a1125f5e200fd43f0e4cffd57ee34f3b9cc0a848267792849d6f5f0", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "v0.1.179 时期 Cindy 分组/账号运维计划(v180)的 SDD 账本:记录基线(base 69478fa、2026-08-24 生产只读审计 27 个 strict Cindy 账号、v4 目录 22 模型/16078 字节 sha)、10 行任务间接口扫描表、7 行任务自洽表、10 条裁定(group_id 端到端、首信号终态、物理级联删除含 usage_logs、迁移 236 失败关闭、预览不设 token、Task 4b 要求 v3 episode 归属)、Task 0–7 的完成与修复轮次(含 commit 区间)以及 2026-08-24 热修 PR #93 合并说明。上游 aea725f 没有 .superpowers 目录,整文件为下游新增的历史过程留档;不含代码,其中提到的文件(如 cindy_capability_catalog.go)的 v0.2.7 归属由各自源码条目判定,本条不作声明。静态阅读,文中的测试通过结论均为文档自述、未复核。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Content anchor: 82 lines — L1 plan pointer; L3-L10 Baseline (base 69478fa0…, 27 strict accounts, 22-model v4 sha b2783df6…, minimal-test ruling); L12-L25 pre-flight interface table; L27-L37 self-consistency table; L39-L49 Rulings; L51-L74 Task ledger (Task 1-6 complete, Task 7 pending); L76-L82 Continuation about hotfix PR #93 / df4feba8.", - "Delta anchor: git ls-tree aea725f -- .superpowers/ prints nothing, so the whole ledger is downstream-new; it is process history for the pre-plugin v0.1.179 line and does not describe v0.2.7 plugin boundaries.", - "Not claimed: none of the recorded test results, production audit numbers or commit ranges were re-verified; no production behavior edit or test execution." - ] - }, - { - "path": ".superpowers/sdd/cindy-group-account-ops-v180/task-3-report.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "311515348143bf947cf3fbdaec0dc982766f06364b4eb21a543e1db5f84344a0", - "review_fingerprint": "311515348143bf947cf3fbdaec0dc982766f06364b4eb21a543e1db5f84344a0", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "v180 计划 Task 3 报告《Cindy 导入预览与规范执行》:记录新增只读预览接口 POST /api/v1/admin/accounts/data/preview、预览与 account-job 执行共用一个决策引擎、仅把 base URL 规范化后等于 Laxa 根的 legacy openai API-key 记录提升为 Cindy 身份、必须显式 strict 目标组并丢弃 legacy 组名、稳定脱敏的 create/update/reject 业务码;RED/GREEN 段落是 go test 命令与结果的文字记录;Files Changed 列出 account_data.go、account_data_import_decision.go、account_job_execution.go、account_job_handler.go、service/account_job.go、service/cindy_identity.go、routes/admin.go;Fix Round 1 关闭 4 个缺陷(GetGroup 由完整成员分类器水合 StrictCindy、pg_advisory_xact_lock 在同一事务内声明设备身份、决策按转换后账号校验、api_key 缺失返回 cindy_import_api_key_invalid),Remaining Risk 指出串行化证明只是 SQL mock。上游 aea725f 无此文件,为下游 v0.1.179 时期的历史过程留档;文中所述导入决策/设备身份逻辑在 v0.2.7 是否已迁入插件由对应源码条目判定,本条不作声明。静态阅读,文中测试结论未复核。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Content anchor: 213 lines — L1-L8 Status (backend-only, worktree codex/cindy-group-ops-v180); L10-L28 Result (preview route, canonical engine, Laxa-root promotion, explicit target group, redacted codes, no preview token); L30-L62 RED evidence (4 go test failures incl. missing target_group_id, GetGroup error propagation, device-source parity, route contract); L64-L100 GREEN evidence; L102-L118 Files Changed; L120-L142 Self-Review; L144-L154 Concerns; L156-L213 Review Fix Round 1 with 4 closed defects, RED/GREEN and Remaining Risk.", - "Delta anchor: git ls-tree aea725f -- .superpowers/ prints nothing, so the whole report is downstream-new process history; it references pre-plugin paths (service/cindy_identity.go, account_data_import_decision.go) whose current ownership is decided in their own records, not here.", - "Not claimed: no test command in the report was re-run; no verification of the described transaction lock or preview behavior; no production behavior edit." - ] - }, - { - "path": ".superpowers/sdd/cindy-group-account-ops-v180/task-4b-report.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "91626c4555f1a87caa0cc7261cd4082ecd67d74b1ff23bea0188f5bfa5c8479b", - "review_fingerprint": "91626c4555f1a87caa0cc7261cd4082ecd67d74b1ff23bea0188f5bfa5c8479b", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "v180 计划 Task 4b 报告(2026-08-24):记录移除对 legacy blockCindyBalanceRuntime 的显式诊断耗尽调用,改为在 lease 保护的数据库提交后经既有 CindyHealthCoordinator 发送精确预算信号,由协调器校验凭证代际/指纹、创建 v3 终态 episode 并持有运行时阻断,并新增“诊断路径产生 episode 归属阻断、不留 legacy 指纹标记”的回归断言。Verification 段是 go test -tags unit ./internal/service -run '^TestCindyBalanceProbe' 等命令的文字记录;Remaining Risk 指出协调器由 ProvideCindyHealthService 注入、缺协调器时只提交 DB 终态且无 legacy 回退,并记下 cindy_balance_pending_test.go:236 一处既有无关失败。上游 aea725f 无此文件,属下游历史过程留档;所述 probe/coordinator 逻辑在 v0.2.7 的归属由对应 service/插件源码条目判定。静态阅读,文中测试结论未复核。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Content anchor: 35 lines — L1-L5 header (task report, complete, last verified 2026-08-24); L7-L16 Changes (drop legacy blockCindyBalanceRuntime call, coordinator-owned v3 terminal episode, focused regression assertion); L18-L24 Verification (unit-tag go test commands, compile-only run, diff scope); L26-L35 Remaining Risk (ProvideCindyHealthService wiring, no legacy fallback, pre-existing unrelated failure at cindy_balance_pending_test.go:236).", - "Delta anchor: git ls-tree aea725f -- .superpowers/ prints nothing, whole file is downstream-new process history; it documents the same probe/coordinator surface that cindy_balance_probe_handler.go in this slice exposes, but ownership of that code is judged in the source records.", - "Not claimed: no test was re-run and the described coordinator behavior was not verified here; no production behavior edit." - ] - }, - { - "path": ".superpowers/sdd/cindy-group-account-ops-v180/task-5-report.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "bc97db159a41247160ae5dbc1bac8e7a86262a0243eb41135ab85a595f3b4d77", - "review_fingerprint": "bc97db159a41247160ae5dbc1bac8e7a86262a0243eb41135ab85a595f3b4d77", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "v180 计划 Task 5 报告《最终成功者用量/统计边界》:记录迁移 238_cindy_account_stats_reset_at.sql 为用量计费去重账本增加 account_id 归属列(原子去重声明返回首个成功账号,重复/乱序 worker 在计费与 usage_log 写入前被拒)、失败/拒答/failover/部分错误响应不再提交用量、重复计费不写第二条 usage 行并失效账号用量缓存与今日统计快照、cindy_account_stats_reset_at 水位以 GREATEST(today_start, reset_at) 作用于单账号与批量窗口 SQL、按规范化 Laxa 凭证指纹分组的脱敏重复身份清单(最老非终态账号为建议 owner);Verification 与 Fix Round(1620bd1fb..HEAD,用量快照扩展到 WS/Chat/Images/Embeddings/Alpha Search 并脱离 Gin 上下文)是 go test 命令的文字记录。上游 aea725f 无此文件,为下游历史过程留档;所述 usage 去重与重复清单逻辑在 v0.2.7 的宿主/插件归属由对应源码(如本切片的 account_cindy_duplicates.go)条目判定。静态阅读,文中测试结论未复核。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Content anchor: 68 lines — L1-L5 Status; L7-L25 Changes (migration 238 account_id owner column, non-billable failed/refusal/failover attempts, cache invalidation, reset_at watermark via GREATEST, redacted duplicate-identity inventory with oldest non-terminal owner); L27-L37 Verification command block; L39-L46 Concerns (PostgreSQL/Redis gates, Ent type lacks watermark so stats read it in SQL); L48-L68 Fix Round 1620bd1fb..HEAD with detached usage snapshot and second command block.", - "Delta anchor: git ls-tree aea725f -- .superpowers/ prints nothing, whole file is downstream-new process history; the duplicate-inventory rule it describes (normalized Laxa fingerprint, oldest non-terminal owner) is the business rule behind admin/account_cindy_duplicates.go reviewed later in this slice.", - "Not claimed: no listed go test command was re-run; migration 238 SQL was not read in this record; no production behavior edit." - ] - }, - { - "path": ".superpowers/sdd/cindy-group-account-ops-v180/task-6-report.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "1aa51a15ae109b429d221c1e901244eeb2dbae1e2748f23236fd6621ab518cfb", - "review_fingerprint": "1aa51a15ae109b429d221c1e901244eeb2dbae1e2748f23236fd6621ab518cfb", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "v180 计划 Task 6 报告《Cindy 管理端 UI 集成》:记录在既有完整账号控制台上加入 Cindy 平台类型/目录/图标/中英文翻译,群组行动作链接到 /admin/accounts 并携带 platforms=cindy&cindy_only=true&group_id= 查询契约,账号控制台路由/列表/导出/分类/探测过滤统一为 group_id,新增独立的 Cindy 封禁指标、预览、确认与 account-job 清理流,接入服务端导入预览 API 与 strict 目标组选择、脱敏逐项预览标签、执行时重校验和任务抽屉交接,并按计划裁定不引入预览 token/指纹门。Verification 段为 pnpm typecheck/eslint/13 个测试文件 44 个用例的文字记录。上游 aea725f 无此文件,为下游 v0.1.179 时期的历史过程留档;文中 UI 契约在 v0.2.7 是否已由 cindy-provider 插件声明或前端 SDK 消费,由前端源码条目判定,本条不作声明。静态阅读,文中测试结论未复核。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Content anchor: 40 lines — L1-L5 Status; L7-L24 Changes (platform types/catalogs/i18n, group-row link query contract platforms=cindy&cindy_only=true&group_id, group_id standardization, Cindy banned metrics + cleanup job flow, import preview integration without token gate, bounded preview table); L26-L35 Verification block (pnpm typecheck, eslint, test:run 13 files/44 tests, git diff --check); L37-L40 Deferred/ruled behavior (no stale-preview token).", - "Delta anchor: git ls-tree aea725f -- .superpowers/ prints nothing, so the whole report is downstream-new process history; it describes the pre-plugin frontend integration that the v0.2.7 cindy-provider ExtensionPage migration later reshaped, and it is not a runtime input.", - "Not claimed: no frontend typecheck, lint or test was run; no browser or visual verification; no production behavior edit." - ] - }, - { - "path": "DOWNSTREAM.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "cc75deaf225a80bdc3e2f39504461377ec77021c37737c93b6190f97408246f4", - "review_fingerprint": "cc75deaf225a80bdc3e2f39504461377ec77021c37737c93b6190f97408246f4", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "下游新增的 fork 总览文档:说明 codexrip 补丁集的来源基线(恢复的 v0.2.6 提交 49a39b6、集成基线 v0.2.5-codexrip.14)、账号测试与 292 ticket 生命周期契约(迁移 244、续期节奏、代理凭据只在管理员响应中出现)、官方行为与下游契约边界、发布/生产部署流程(不可变 vX.Y.Z-codexrip.N 标签、ghcr 镜像、deploy-preserve、受限 SSH 更新器、无自动回滚)以及“定时发现上游新版本不能直接部署生产”的原则。其 Source baseline 段仍写 v0.2.6,而本分支 .downstream/upstream-base 已是 v0.2.7,文档滞后于本次审计基线(findings,低)。纯文档,reference;静态阅读,未对照运行系统。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "L5-L12 source baseline (v0.2.6 commit 49a39b6, base v0.2.5-codexrip.14) — .downstream/upstream-base on this branch reads 'v0.2.7' and .downstream/upstream-risk.json still records upstream_tag v0.2.6/upstream_base v0.2.5.", - "L14-L22 ticket lifecycle contracts (migration 244_codex_ticket_lifecycle.sql, renewal 60s before/after expiry, proxy credential exposure rules); L24-L40 official-behavior boundaries; L42-L58 release/deploy statements consistent with production-deploy.yml (deploy-preserve, restricted SSH, health != model functionality); L60-L64 upstream discovery cannot deploy.", - "New downstream file (no upstream blob). Whole 64-line file read.", - "Static read only; documentation content was not verified against a running system." - ] - }, - { - "path": "Dockerfile", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "9a5523deb5c9095c966e05fd56d3fce930ffab83f01dcdb1f5dbbc456ae4395d", - "review_fingerprint": "9a5523deb5c9095c966e05fd56d3fce930ffab83f01dcdb1f5dbbc456ae4395d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "正式参数选择 plugin-bundle-release:COPY deploy/plugin-bundle 后仅 verify-bundle,再 COPY 同一 current 目录到 /app/bundled-plugins,不重建/重签包。development stage 独立生成合成 key。Artifact build 只编译,不运行业务测试。原 runtime/entrypoint/health 行为未改。", - "evidence": [ - "release stage lines119-123", - "dynamic stage selection", - "runtime COPY line174", - "SUB2API_ARTIFACT_BUILD compile flag", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": "Dockerfile.goreleaser", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "0ee54a55155ddd1602ccbedd6c27814a3935f152bb8931d07dc695d660a84b53", - "review_fingerprint": "0ee54a55155ddd1602ccbedd6c27814a3935f152bb8931d07dc695d660a84b53", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "GoReleaser 用的运行时镜像(alpine + 版本匹配的 pg_dump/psql,非 root 用户 sub2api)。下游相对上游三处改动:把 THIRD_PARTY_NOTICES.md 复制进 /app;新建可写的 /app/skill-registry 目录供运行时配对注册表快照使用;chown 从递归整个 /app 收窄为二进制、/app/data 与 /app/skill-registry。其余 apk 依赖、pg 客户端复制、entrypoint、HEALTHCHECK 与上游一致;与根 Dockerfile L176-L180 及 deploy/Dockerfile L109-L113 的同类改动保持一致。未构建镜像,静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +4/-2 at L48 (COPY THIRD_PARTY_NOTICES.md), L50-L52 (mkdir /app/data /app/skill-registry; chown sub2api binary+data+skill-registry instead of chown -R /app); upstream blob 804fb05e. Whole 65-line file read.", - "Consumers of the new paths: deploy/docker-entrypoint.sh L8-L10 mkdir/chown the same two directories at start; .dockerignore L14 '!THIRD_PARTY_NOTICES.md' allows the COPY; identical stanza exists in Dockerfile L176-L180 and deploy/Dockerfile L109-L113.", - "No secrets, no network endpoints, no production host references in the file.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": "Makefile", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "61bc7a132fa114d5f61fbdcadd9dfe55b32679ad16c468dfcfd13f3256473eb0", - "review_fingerprint": "61bc7a132fa114d5f61fbdcadd9dfe55b32679ad16c468dfcfd13f3256473eb0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Build/test entrypoints continue to call the backend Makefile and frontend lint/typecheck plus explicit critical Vitest targets. The downstream list adds affected account/sidebar/Cindy coverage. Static review found and corrected the stale Cindy test filter to its moved independent-plugin path; no required check or test was removed.", - "evidence": [ - "Complete Makefile and exact upstream delta read. Initial path check found the stale Cindy path; after its correction all 22 explicit targets exist and the current Vitest include admits the plugin path. No test/build target was run.", - "artifacts/evidence/v027-lifecycle-wiring-review.json" - ] - }, - { - "path": "README.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "9b8fcc36729dbb0269d72865d24b87b54ab5d9b48a83e052caaf1c1ed31ddd93", - "review_fingerprint": "9b8fcc36729dbb0269d72865d24b87b54ab5d9b48a83e052caaf1c1ed31ddd93", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "上游英文 README(赞助商表、功能列表、四种部署方式、config.yaml 安全项、OpenAI Responses WebSocket 入口限制与 force_http、Grok/xAI、Antigravity、项目结构)。下游相对上游只改了两处文本:L7 Go 徽章与 L203 技术栈表由 Go 1.27.0 改为 1.26.6。但 backend/go.mod 声明 go 1.27.0,backend-ci/release/security-scan 均硬断言 go1.27.0,三个 Dockerfile 使用 golang:1.27.0-alpine,因此这一下游改动是过期的版本文案回退(合并时保留了旧下游值),见 findings(低)。其余 901 行与上游一致。纯文档,静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: exactly 2 changed lines, L7 badge and L203 'Backend | Go 1.26.6, Gin, Ent' (upstream: 1.27.0); upstream blob 3d6fd891. Whole 905-line file read in two chunks (L1-L500, L501-L905).", - "Cross-check of the delta: backend/go.mod 'go 1.27.0'; .github/workflows/backend-ci.yml L41/L87, release.yml L120, security-scan.yml L27 grep 'go1.27.0'; Dockerfile L11, deploy/Dockerfile L10, backend/Dockerfile L1 golang:1.27.0-alpine; DEV_GUIDE.md L56 documents 1.27.0 as mandatory.", - "No downstream-specific feature text was added to this file; the codexrip release flow is documented in DOWNSTREAM.md and deploy/README.md instead.", - "Static read only; documentation content was not verified against a running system." - ] - }, - { - "path": "README_CN.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "d281253d4ddde5e56bb79af0aa392d9fc28bb7c6e62abc4c7f73dc86043e69ba", - "review_fingerprint": "d281253d4ddde5e56bb79af0aa392d9fc28bb7c6e62abc4c7f73dc86043e69ba", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "上游中文 README;下游 delta 同样只有 L7 徽章与 L205 技术栈两处 Go 1.27.0→1.26.6,与 go.mod/CI/Dockerfile 的 1.27.0 不一致(findings,低)。全文 821 行已读:含 Codex Fast/Flex 策略说明、datamanagementd 数据管理、h2c 与 HTTP/1.1 回退、OpenAI 图片模型(gpt-image-2.5)等中文特有章节,均为上游内容而非下游新增。纯文档,静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: 2 changed lines (L7, L205), upstream blob 9a4907c4; whole file read in two chunks (L1-L500, L501-L821).", - "Same 1.26.6 vs 1.27.0 inconsistency as README.md (backend/go.mod, CI assertions, Dockerfiles all say 1.27.0).", - "Sections L222-L244 (Codex Fast/Flex), L429-L439 (datamanagementd), L678-L699 (h2c), L725-L731 (OpenAI image models) are unchanged upstream text.", - "Static read only; documentation content was not verified against a running system." - ] - }, - { - "path": "README_JA.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "dfa35d21032931dfd5975d6e638d3134119190170f7aa177544d5f83ccb5dfc9", - "review_fingerprint": "dfa35d21032931dfd5975d6e638d3134119190170f7aa177544d5f83ccb5dfc9", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "上游日文 README;下游 delta 只有 L7 徽章与 L204 技术栈两处 Go 1.27.0→1.26.6(findings,低),其余 743 行(赞助商、部署四种方式、安全配置、管理员账号创建、Antigravity、项目结构)与上游一致。纯文档,静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: 2 changed lines (L7, L204), upstream blob ca94ba55; whole file read in two chunks (L1-L500, L501-L745).", - "Same 1.26.6 vs 1.27.0 inconsistency as README.md / README_CN.md.", - "No downstream-specific content added.", - "Static read only; documentation content was not verified against a running system." - ] - }, - { - "path": "THIRD_PARTY_NOTICES.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "92b668fbb5e1b8ff5b36e69ccf662be781c9c3f1941f60d14b1ea592a09ba2aa", - "review_fingerprint": "92b668fbb5e1b8ff5b36e69ccf662be781c9c3f1941f60d14b1ea592a09ba2aa", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "下游新增的第三方声明:(1) MDX-Tom/gpt-5.6-instruct v45 的 Markdown 提示词正文(提交 77e7a64、制品/正文/许可证三份 SHA-256、MIT 许可全文),说明它只作为可选且默认未激活的系统提示词模板导入,不执行其安装脚本也不改本地 Codex 配置;(2) 前端内置的小米 MiSans Web 字体及其 IP 许可证 PDF 与 NOTICE 路径。已核对四个哈希/提交值与 plugins/prompt-skills/source/support.go、gpt56.go 及 service/repository 测试中的常量逐字一致,MiSans 许可证 PDF 与 NOTICE.md 存在于 frontend/public/fonts/misans/。该文件被 Dockerfile、deploy/Dockerfile、Dockerfile.goreleaser 复制进镜像 /app。纯文档,静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "New downstream file (no upstream blob); whole 43-line file read. L3-L16 gpt-5.6-instruct provenance, L18-L39 MIT text, L41-L43 MiSans notice.", - "Hash cross-check via rg: SourceCommit 77e7a649... and SourceArtifactSHA256 c86c2c6d... in plugins/prompt-skills/source/support.go L35; GPT56PromptLicenseSHA256 edb45f4c... in plugins/prompt-skills/source/gpt56.go L26; prompt SHA c71c50e2... asserted in backend/internal/service/business_system_prompt_service_test.go L218.", - "ls confirms frontend/public/fonts/misans/NOTICE.md and MiSans-Font-Intellectual-Property-License.pdf exist; .dockerignore L14 whitelists the notice for the image COPY steps.", - "Static read only; documentation content was not verified against a running system." - ] - }, - { - "path": "backend/.golangci.yml", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2d837b357922814442a074592881c4ab381aa63551ebd6bcdbf5019f086072f0", - "review_fingerprint": "2d837b357922814442a074592881c4ab381aa63551ebd6bcdbf5019f086072f0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Downstream configuration removes diagnostic-count truncation and extends an existing test-file-only taint exception to G702. Production depguard/errcheck/gosec/govet/staticcheck/unused settings and their upstream exclusions are not further broadened by this delta. This is a configuration review, not a successful linter/CVE or complete SQL-injection assessment.", - "evidence": [ - "Full YAML read against official v0.2.7 delta; _test.go path remains required for G70[234] waiver and the regular CI linter is not disabled.", - "artifacts/evidence/v027-lifecycle-wiring-review.json" - ] - }, - { - "path": "backend/cmd/cleanup-ingress-reject-logs/main.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "23a419fcd3d261790d7ddfa260bd31747cac19f1cf924e0ea2c1f3323ba97776", - "review_fingerprint": "23a419fcd3d261790d7ddfa260bd31747cac19f1cf924e0ea2c1f3323ba97776", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "一次性运维 CLI:按 --before 游标分批扫描 ops_error_logs 中 error_phase='auth' 且无上游信息的行,用 historicalIngressRejectReason 按错误码/固定文案归类,--execute 时批量 DELETE。下游相对上游只有两处:删除 github.com/lib/pq 导入,DELETE ... WHERE id = ANY($1) 的参数从 pq.Array(ids) 改为直接传 []int64(提交 ae801a079 “replace vulnerable PostgreSQL driver”)。该改动与 repository.InitEnt 现在经 openPostgresDB 走 pgx/v5 stdlib 驱动配套:pgx 原生把 Go 切片编码为 PG 数组,lib/pq 下裸切片会报 unsupported type,因此这是跟随驱动替换的核心正确性修正,不涉及任何插件业务规则。静态阅读,未执行、未连库。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "L30-L81 main(): flags --before(RFC3339,必填)/--execute/--batch-size(1-5000),config.LoadForBootstrap() 与 repository.InitEnt(cfg) 建连,打印 mode/classifier sha256/scanned/matched/deleted 及按 reason 排序的计数。", - "L83-L145 cleanup(): 以 id 游标 + LIMIT 分批 SELECT(error_phase='auth' AND account_id IS NULL AND upstream_* 为空),L131-L142 仅在 execute 时 DELETE ... WHERE id = ANY($1) AND created_at < $2,二次带 created_at 条件避免误删新行。", - "git diff aea725f: 仅 -\"github.com/lib/pq\" 导入与 L133 pq.Array(ids)→ids 两处;L147-L217 分类表(API_KEY_REQUIRED/INVALID_API_KEY/.../中文分组文案/IP ACL 前缀)与上游完全一致。", - "调用链: repository/ent.go:113 InitEnt → openPostgresDB(dsn, EnableServerTiming) 返回 pgx stdlib 的 *sql.DB(下游新增),isTransientDatabaseInitializationError 同时识别 pgconn.PgError 与 pq.Error;go.mod 同时保留 jackc/pgx/v5 v5.10.0 与 lib/pq v1.10.9。", - "未宣称:未运行该 CLI、未验证 pgx 对 []int64 的实际编码行为,仅依据源码与驱动切换提交推断。" - ] - }, - { - "path": "backend/cmd/package-plugin/bundle.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c1b0108de0c4f57ccd535b655da3af15b58534c5f0681faf0dd0d1deb1b2e9fa", - "review_fingerprint": "c1b0108de0c4f57ccd535b655da3af15b58534c5f0681faf0dd0d1deb1b2e9fa", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "目录/平台/版本严格校验,bundle 输出目录必须空,模块唯一;允许单 domain 选择,默认遍历 inventory 全七包。构建接受预定二进制目标,不载入 signing key,并显式移除子进程的 SUB2API_PLUGIN_SIGNING_KEY 环境。", - "evidence": [ - "packageBundle empty output/matched domain", - "buildBundleBinaries env filter and fixed go build argv", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": "backend/cmd/package-plugin/main.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "3be27bafe2129f6f1847fda8e51adddc91ba764cc74d13ad53e7acb5327b2efb", - "review_fingerprint": "3be27bafe2129f6f1847fda8e51adddc91ba764cc74d13ad53e7acb5327b2efb", - "review_status": "pending" - }, - { - "path": "backend/cmd/package-plugin/verify.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f9a01f1f73e9f838998894bc25a55921356e4e5faaa387ada7fbf1cd9b81981a", - "review_fingerprint": "f9a01f1f73e9f838998894bc25a55921356e4e5faaa387ada7fbf1cd9b81981a", - "review_status": "pending" - }, - { - "path": "backend/cmd/profit-preview/main.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": false, - "content_sha256": null, - "deleted_upstream_blob": "2c351410c9228baa799d662f967a7af13fc19c1e", - "review_fingerprint": "2522a9fd913c9b940f284402f5df416c7a0a753d142f3b6bfb3548f5b70a4f63", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "读取导出group/account/user override/model JSON,支持assume-enabled与JSON输出,计算default/minimum-D阈值并警告零admitted模型;不是schema迁移或在线账务入口。 有历史删除意图且runtime门现已固定关闭;保留删除不会删掉历史列、倍率或账务记录。不能宣称原preview算法仍有端到端覆盖。", - "evidence": [ - "Exact deleted blob and replacement assertion mapping: artifacts/evidence/v027-astra-deleted-path-review.json", - "该已删文件及旧profit-preview均未运行;独立dormant证据记录限定服务回归。", - "Deletion basis: 5f216d1d07f091b8942aa70e3c5ee3d7fc4153fe", - "The bound dormant implementation is included with this review; its exact eight source SHA256 values were verified before import." - ] - }, - { - "path": "backend/cmd/profit-preview/main_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": false, - "content_sha256": null, - "deleted_upstream_blob": "9b6d185c5b01db62aed68bde7cfebf9f29e7b1a5", - "review_fingerprint": "1a9e7c068cddb5321c8b7cc5970393d8b47a9e167419b08e91878606126b8762", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "包括忽略null override而非把它当0、拒绝空groups、区分default-D与minimum-D的零模型告警。 与CLI一并继续删除有证据支持;不把本次两项runtime回归冒称上述输入/输出测试的替代。", - "evidence": [ - "Exact deleted blob and replacement assertion mapping: artifacts/evidence/v027-astra-deleted-path-review.json", - "该已删文件及旧profit-preview均未运行;独立dormant证据记录限定服务回归。", - "Deletion basis: 5f216d1d07f091b8942aa70e3c5ee3d7fc4153fe", - "The bound dormant implementation is included with this review; its exact eight source SHA256 values were verified before import." - ] - }, - { - "path": "backend/cmd/server/VERSION", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5b57e3b8c153d1d33b0c0f1ee29d3de1bf93232ed95aa78b80fe885e99faa915", - "review_fingerprint": "5b57e3b8c153d1d33b0c0f1ee29d3de1bf93232ed95aa78b80fe885e99faa915", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "单行版本号文件,当前内容为 0.2.7(带换行,6 字节)。下游相对上游 aea725f 的差异是 0.2.5→0.2.7,来自提交 5a4b26a1d“integrate official Sub2API v0.2.7 baseline”,即把上游 tag 尚未更新的版本文件对齐到 v0.2.7 发布号。它经 cmd/server/main.go 的 //go:embed VERSION 作为 ldflags 未注入时的默认 Version,并被 Dockerfile 通过 scripts/resolve-version.sh 读取,属于构建/发布机制而非任何插件业务。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "cat -A 显示内容为 `0.2.7$`(一行加换行);git diff aea725f: -0.2.5 / +0.2.7,最后修改提交 5a4b26a1d (2026-09-19 merge official v0.2.7 baseline)。", - "消费方: backend/cmd/server/main.go:32-54 //go:embed VERSION → init() 在 Version 未由 -X main.Version 注入时 TrimSpace 后使用,空则回退 0.0.0-dev;Dockerfile:98-107 版本优先级 build arg VERSION > git tag > cmd/server/VERSION(resolve-version.sh)。", - "未宣称:未构建镜像、未运行 resolve-version.sh。" - ] - }, - { - "path": "backend/cmd/server/main.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "470861ec515b5d3cd2b595efa441f7d67da1e5b24cbc30dfdaca5d27c2554f71", - "review_fingerprint": "470861ec515b5d3cd2b595efa441f7d67da1e5b24cbc30dfdaca5d27c2554f71", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "服务进程入口:嵌入 VERSION、解析 -setup/-version 标志、首次运行走 setup 向导或 AutoSetupFromEnv,否则 wire 注入 Application 后依次启动子系统并优雅关停。下游相对上游新增两块:(1) -verify-codex-context-contract 离线自检标志,runCodexContextContractVerificationWith 仅做参数互斥校验(与 -setup/-version/位置参数同用返回 2)、调用 service.VerifyOfficialCodexContextContract 并只打印固定成功/失败行(错误细节不外泄);(2) runMainServer 在 PluginManager/PromptAudit 之后按需启动 PromptDomain、CodexIdentity、AccountJobs、ImageStudio(后者受 service.ImageStudioFeatureEnabled 门控),AccountJobs/ImageStudio 启动失败时 Cleanup 后 exit(1)。这些都是宿主启动编排,不含业务规则,判为 core;上下文契约与各 runtime 的实质逻辑分别在 service/openai_codex_context_contract.go 与各 *_runtime.go(其他切片),此处不评价其是否与 model-policy/codex-runtime 插件重复。静态阅读,未构建运行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "git diff aea725f: +import fmt/io/service;L65-L82 新增 -verify-codex-context-contract 分支;L117-L150 新增 runCodexContextContractVerification(With);L225-L244 新增 PromptDomain.Start/CodexIdentity.Start/AccountJobs.Start/ImageStudio.Start 四段。L152-L187 runSetupServer 与 L246-L269 启动/SIGINT/SIGTERM 5s Shutdown 与上游一致(PluginManager/PromptAudit 启动亦为上游已有)。", - "调用链: service/openai_codex_context_contract.go:12-14 定义 OfficialCodexContextContract{Success,Failure}Line/InvalidArgsLine 常量,:36 VerifyOfficialCodexContextContract();wire.go:30-35 Application 字段 PromptAudit/PluginManager/AccountJobs(*service.AccountJobRuntime)/ImageStudio(*service.ImageStudioRuntime)/PromptDomain(*service.PromptDomainRuntime)/CodexIdentity(*service.CodexClientIdentityBackfillService);Start 定义于 service/account_job.go:433、prompt_domain_runtime.go:49、image_studio_runtime.go:61、openai_codex_client_identity.go:215;ImageStudioFeatureEnabled 定义于 service/cindy_feature_flags.go:84。", - "观察: AccountJobs/ImageStudio 启动失败走 app.Cleanup()+os.Exit(1),而 defer app.Cleanup() 不会再执行(进程退出),无双重清理问题;PromptDomain.Start 无返回值、CodexIdentity.Start() 不接收 ctx,取消依赖各自 runtime 内部实现,未在此文件核实。", - "最后修改提交: 480ec3988/dce661215/990dede9b (2026-09-20 插件隔离系列)。未宣称:未运行二进制、未验证 -verify-codex-context-contract 的实际输出。" - ] - }, - { - "path": "backend/cmd/server/main_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d11f20eaa62ba7032e92bcd2ac68286646f10b3da3ce60a897cc817a39fde674", - "review_fingerprint": "d11f20eaa62ba7032e92bcd2ac68286646f10b3da3ce60a897cc817a39fde674", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "下游新增测试文件(上游 aea725f 无此路径),对应 main.go 新增的 -verify-codex-context-contract 入口。三个用例分别断言:正常调用返回 0 并恰好输出 OfficialCodexContextContractSuccessLine 一行;注入返回 error 的 verify 函数时返回 1、输出固定失败行且不含错误细节(防泄漏);与 -setup/-version/位置参数同用时返回 2 并输出 InvalidArgsLine。证明的是宿主 CLI 包装层的退出码与输出契约,不证明契约内容本身(那在 service 包)。第一个用例会真实调用 service.VerifyOfficialCodexContextContract,属于纯内存自检。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "L12-L16 TestRunCodexContextContractVerification: exit 0 + SuccessLine+\"\n\";L18-L30 ...FailsWithFixedShape: 注入 verify 返回 (\"sensitive-detail\", err) → exit 1、输出 FailureLine、NotContains sensitive-detail;L32-L54 ...RejectsConflictingArguments: setup/version/positional 三子用例 → exit 2 + InvalidArgsLine。", - "被测对象 main.go:117-150 runCodexContextContractVerification(With);常量来源 service/openai_codex_context_contract.go:12-14。git ls-tree aea725f 无此文件,首次提交 97a0547db (2026-08-29 fix(codex): verify context contract in runtime binary)。", - "未宣称:未运行 go test;未评价 service 侧契约固定值(priority=custom,official,upstream,default / default_context=200000)是否正确。" - ] - }, - { - "path": "backend/cmd/server/wire.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e87bdcc560bed61d44b974ff80da149f1dfee8268eaec0d49ccb5ff4844b70c3", - "review_fingerprint": "e87bdcc560bed61d44b974ff80da149f1dfee8268eaec0d49ccb5ff4844b70c3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Application composition includes the independent plugin manager and host-owned task/media/prompt/backfill lifecycles. Cleanup stops prompt initialization before parallel producers, then drains plugins while Redis/Ent remain available, and closes infrastructure last. Restored the already-started upstream quota-auto-reset Stop call; this is not revival of a removed downstream ticket/overdraft executor. The ten-second context is not a hard bound on all Stop implementations.", - "evidence": [ - "Full wire.go read, generated counterpart checked, and the new real-worker/in-memory-repository cancellation regression passed.", - "artifacts/evidence/v027-lifecycle-wiring-review.json" - ] - }, - { - "path": "backend/cmd/server/wire_gen.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "c338078e2c913c4de1f5b18485d5d677a86984f16ed175e81bf90c911b054004", - "review_fingerprint": "c338078e2c913c4de1f5b18485d5d677a86984f16ed175e81bf90c911b054004", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "core-extension-and-job-host", - "reason": "Wire-generated application assembly was regenerated from current wire.go and provider sets, not manually patched. The only generated delta is the six-line upstream auto-reset cleanup step, matching its canonical source; no dependency or schema output changed.", - "evidence": [ - "go generate ./cmd/server completed successfully and reported the generated file; git diff shows only the intended cleanup block. cmd/server targeted test compiled and exercised the generated provider.", - "artifacts/evidence/v027-lifecycle-wiring-review.json" - ] - }, - { - "path": "backend/cmd/server/wire_gen_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "557f2ba708819c27d79e4430576c1eaaca29ec4ee4ec26e5184041adf0eea54c", - "review_fingerprint": "557f2ba708819c27d79e4430576c1eaaca29ec4ee4ec26e5184041adf0eea54c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Existing minimal dependency cleanup construction is reused. A real auto-reset worker receives a synthetic account notification and blocks in the fake GetByID; cleanup must cancel that exact context. Quota-query/reset/cache methods explicitly fail the test if reached. All constructors use local/nil dependencies; t.Cleanup also stops the worker on red-test failure.", - "evidence": [ - "Before fix the actual worker context remained uncancelled (RUN/FAIL, 0.079s). After regeneration the exact test RUN/PASS (0.083s) and logs include OpenAIQuotaAutoResetService stop. The old nil smoke test was not redundantly rerun.", - "artifacts/evidence/v027-lifecycle-wiring-review.json" - ] - }, - { - "path": "backend/ent/account.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "2add31c5bd90b14b6c5f5f84097de3782245bc41ef5e0d0d0e826cdf1562ef29", - "review_fingerprint": "2add31c5bd90b14b6c5f5f84097de3782245bc41ef5e0d0d0e826cdf1562ef29", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=2add31c5bd90b14b6c5f5f84097de3782245bc41ef5e0d0d0e826cdf1562ef29", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=a1cd1a73b6c83949e10355eacf0f7e436301ec0a", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/account/account.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "c7a4bbc08a60ac25fb3d0a5a16dc2a6507c9c3e6062221e8c671e1ca80e98e95", - "review_fingerprint": "c7a4bbc08a60ac25fb3d0a5a16dc2a6507c9c3e6062221e8c671e1ca80e98e95", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=c7a4bbc08a60ac25fb3d0a5a16dc2a6507c9c3e6062221e8c671e1ca80e98e95", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=61a8a8213282f32802bacb789ce968f0f2c51751", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/account/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "0d493f7f8ca9bf8eabdd6eee04b411e0676ac5e9f8d54b412a9985b1ef5317cf", - "review_fingerprint": "0d493f7f8ca9bf8eabdd6eee04b411e0676ac5e9f8d54b412a9985b1ef5317cf", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=0d493f7f8ca9bf8eabdd6eee04b411e0676ac5e9f8d54b412a9985b1ef5317cf", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=6b7c375be7ca846d05b28baebf997101d8a69d21", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/account_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "e9696b606b01b525eca62133d739c7862b25e18b3564d39498a40dc3f1b406ce", - "review_fingerprint": "e9696b606b01b525eca62133d739c7862b25e18b3564d39498a40dc3f1b406ce", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=e9696b606b01b525eca62133d739c7862b25e18b3564d39498a40dc3f1b406ce", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=d74b10eba7770307a26de1517c891301e9d8db92", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/account_query.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "c8609e0d3656d3b692b83367ff5844573ffa127dbbff05ca7b57d5e7c3f606e5", - "review_fingerprint": "c8609e0d3656d3b692b83367ff5844573ffa127dbbff05ca7b57d5e7c3f606e5", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=c8609e0d3656d3b692b83367ff5844573ffa127dbbff05ca7b57d5e7c3f606e5", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=f774d5bd95f14eb60c5bd644049b8cfc73c221d8", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/account_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "ca5117f428ac9c8981d801d0edff04ea147ab7a3185e04832dc4b34e561ef2fd", - "review_fingerprint": "ca5117f428ac9c8981d801d0edff04ea147ab7a3185e04832dc4b34e561ef2fd", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=ca5117f428ac9c8981d801d0edff04ea147ab7a3185e04832dc4b34e561ef2fd", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=4584a826a0434110a757988a0c99c38b9dc0f4b2", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accountfolder.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "3e2a12a02bab08105ee365b4ead3ca78d0f1c66db690bf856efffb84e831f3bb", - "review_fingerprint": "3e2a12a02bab08105ee365b4ead3ca78d0f1c66db690bf856efffb84e831f3bb", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=3e2a12a02bab08105ee365b4ead3ca78d0f1c66db690bf856efffb84e831f3bb", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accountfolder/accountfolder.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "1dd6496fa022a59203f3e538a0669e19002d5174ed96c5f2bf601fc3c0ee2902", - "review_fingerprint": "1dd6496fa022a59203f3e538a0669e19002d5174ed96c5f2bf601fc3c0ee2902", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=1dd6496fa022a59203f3e538a0669e19002d5174ed96c5f2bf601fc3c0ee2902", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accountfolder/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "281920405512f6f5c60658d8aaab67f6f8657d5a17cc0386b5da3c5a0c43cb48", - "review_fingerprint": "281920405512f6f5c60658d8aaab67f6f8657d5a17cc0386b5da3c5a0c43cb48", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=281920405512f6f5c60658d8aaab67f6f8657d5a17cc0386b5da3c5a0c43cb48", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accountfolder_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "25e7eac6f85b807aebe84498243b8edc4ea74b5f5bbe6526d86e008ac76914b3", - "review_fingerprint": "25e7eac6f85b807aebe84498243b8edc4ea74b5f5bbe6526d86e008ac76914b3", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=25e7eac6f85b807aebe84498243b8edc4ea74b5f5bbe6526d86e008ac76914b3", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accountfolder_delete.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "04e055a9decd39d365d3309af20de92dc448c4834a514c6f6cba3353fdf25965", - "review_fingerprint": "04e055a9decd39d365d3309af20de92dc448c4834a514c6f6cba3353fdf25965", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=04e055a9decd39d365d3309af20de92dc448c4834a514c6f6cba3353fdf25965", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accountfolder_query.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "bea6a70f5f4a31042aa5b992e4b47bad7648c2349dd913d8d85f7fecb8f8d309", - "review_fingerprint": "bea6a70f5f4a31042aa5b992e4b47bad7648c2349dd913d8d85f7fecb8f8d309", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=bea6a70f5f4a31042aa5b992e4b47bad7648c2349dd913d8d85f7fecb8f8d309", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accountfolder_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "ea7eae7c9bc4b423ceb50e7b4f27e4f9edc2b3116823784d4cbb26117279dfbd", - "review_fingerprint": "ea7eae7c9bc4b423ceb50e7b4f27e4f9edc2b3116823784d4cbb26117279dfbd", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=ea7eae7c9bc4b423ceb50e7b4f27e4f9edc2b3116823784d4cbb26117279dfbd", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttag.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "3fb76418349769f7c318c176e74ba60f13b65c774954edc5a8e8a04657c91661", - "review_fingerprint": "3fb76418349769f7c318c176e74ba60f13b65c774954edc5a8e8a04657c91661", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=3fb76418349769f7c318c176e74ba60f13b65c774954edc5a8e8a04657c91661", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttag/accounttag.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "c1e334780bdd53c957c2db95c52e0f374dbe2cc58dc3963c8f799e56e11879eb", - "review_fingerprint": "c1e334780bdd53c957c2db95c52e0f374dbe2cc58dc3963c8f799e56e11879eb", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=c1e334780bdd53c957c2db95c52e0f374dbe2cc58dc3963c8f799e56e11879eb", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttag/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "d13cbc12f4af373489639f150df08740c3f33b5fd12bccd08295a0f52d0c8b51", - "review_fingerprint": "d13cbc12f4af373489639f150df08740c3f33b5fd12bccd08295a0f52d0c8b51", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=d13cbc12f4af373489639f150df08740c3f33b5fd12bccd08295a0f52d0c8b51", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttag_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "89a571174d3b006b370243620a53dfe03388c190effa4adc043bede87282db45", - "review_fingerprint": "89a571174d3b006b370243620a53dfe03388c190effa4adc043bede87282db45", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=89a571174d3b006b370243620a53dfe03388c190effa4adc043bede87282db45", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttag_delete.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "b9c01caf2b362ccb49e85bc11e4bedb545cb610d39083b34f0cc9e32773a135a", - "review_fingerprint": "b9c01caf2b362ccb49e85bc11e4bedb545cb610d39083b34f0cc9e32773a135a", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=b9c01caf2b362ccb49e85bc11e4bedb545cb610d39083b34f0cc9e32773a135a", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttag_query.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "8fcc2576866c38e06dc307ea64787ae51ed4af53b85732a40111b709c6182f88", - "review_fingerprint": "8fcc2576866c38e06dc307ea64787ae51ed4af53b85732a40111b709c6182f88", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=8fcc2576866c38e06dc307ea64787ae51ed4af53b85732a40111b709c6182f88", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttag_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "f8dbe2056afd069143335fbf5384e918ae4880b3bf5b15abf543363b02c12cd7", - "review_fingerprint": "f8dbe2056afd069143335fbf5384e918ae4880b3bf5b15abf543363b02c12cd7", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=f8dbe2056afd069143335fbf5384e918ae4880b3bf5b15abf543363b02c12cd7", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttagbinding.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "acf0d361ec59feb0ec4b3d8947f7452b4e3edd13ded73788e20200e794bc8762", - "review_fingerprint": "acf0d361ec59feb0ec4b3d8947f7452b4e3edd13ded73788e20200e794bc8762", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=acf0d361ec59feb0ec4b3d8947f7452b4e3edd13ded73788e20200e794bc8762", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttagbinding/accounttagbinding.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "4ce3747ed63e6d1f2a3c9fe86f828235da66d4f0a7dae563a59f1584dc2ca0b4", - "review_fingerprint": "4ce3747ed63e6d1f2a3c9fe86f828235da66d4f0a7dae563a59f1584dc2ca0b4", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=4ce3747ed63e6d1f2a3c9fe86f828235da66d4f0a7dae563a59f1584dc2ca0b4", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttagbinding/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "ea4a129097089b6b3cae09bd53c907db699ce555defea5fd667b041ce2efb42d", - "review_fingerprint": "ea4a129097089b6b3cae09bd53c907db699ce555defea5fd667b041ce2efb42d", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=ea4a129097089b6b3cae09bd53c907db699ce555defea5fd667b041ce2efb42d", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttagbinding_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "6f9261568b9d535d51b4ee6be5cedd34cd99b34c89799c28ee9dd4e379f3f4d0", - "review_fingerprint": "6f9261568b9d535d51b4ee6be5cedd34cd99b34c89799c28ee9dd4e379f3f4d0", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=6f9261568b9d535d51b4ee6be5cedd34cd99b34c89799c28ee9dd4e379f3f4d0", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttagbinding_delete.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "b4e6fb77d0de65efef3832844fcf74562cc91f7db356f66caf651671291e9f93", - "review_fingerprint": "b4e6fb77d0de65efef3832844fcf74562cc91f7db356f66caf651671291e9f93", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=b4e6fb77d0de65efef3832844fcf74562cc91f7db356f66caf651671291e9f93", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttagbinding_query.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "a455d931609204f1f04b16f47a63b2d462c043a1216956ebd511d7e530caf9ac", - "review_fingerprint": "a455d931609204f1f04b16f47a63b2d462c043a1216956ebd511d7e530caf9ac", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=a455d931609204f1f04b16f47a63b2d462c043a1216956ebd511d7e530caf9ac", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/accounttagbinding_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "e3682f89e70ee48eb3bd05441d875502afb09a1b8a671d1cfe74a40de4eefbed", - "review_fingerprint": "e3682f89e70ee48eb3bd05441d875502afb09a1b8a671d1cfe74a40de4eefbed", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=e3682f89e70ee48eb3bd05441d875502afb09a1b8a671d1cfe74a40de4eefbed", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/apikey.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "35af8a2ebec7554d13f9cbbd0d894b37dc26366d424bdc26d5c1cc05041adfbd", - "review_fingerprint": "35af8a2ebec7554d13f9cbbd0d894b37dc26366d424bdc26d5c1cc05041adfbd", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=35af8a2ebec7554d13f9cbbd0d894b37dc26366d424bdc26d5c1cc05041adfbd", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=9ee660c2da6937c75908c66812d564fb9b9d1868", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/apikey/apikey.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "436a0cbfad4ebc3af7a6b34402a9937dae69a693833e962de883269009e81348", - "review_fingerprint": "436a0cbfad4ebc3af7a6b34402a9937dae69a693833e962de883269009e81348", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=436a0cbfad4ebc3af7a6b34402a9937dae69a693833e962de883269009e81348", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=d398a027b867e7303c839d6dd1c910e6acd30afd", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/apikey/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "a4fdeb1a2585e3167f07be929d91f775b81fa544a1f60cb814451ca110415b04", - "review_fingerprint": "a4fdeb1a2585e3167f07be929d91f775b81fa544a1f60cb814451ca110415b04", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=a4fdeb1a2585e3167f07be929d91f775b81fa544a1f60cb814451ca110415b04", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=edd2652baaedd10d168e316a0e75542ffb3012e0", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/apikey_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "5cb4eed32f9898618ef821d0a5030afeff4c5d7b3de884a71f44f2e99e325fd8", - "review_fingerprint": "5cb4eed32f9898618ef821d0a5030afeff4c5d7b3de884a71f44f2e99e325fd8", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=5cb4eed32f9898618ef821d0a5030afeff4c5d7b3de884a71f44f2e99e325fd8", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=4ec8aeaae4e38f9aaef18675d717b90368598e6e", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/apikey_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "2a681e3395473336fcc3aa3c25dfa921f7dc254dcf01eed8662f430f1fee200d", - "review_fingerprint": "2a681e3395473336fcc3aa3c25dfa921f7dc254dcf01eed8662f430f1fee200d", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=2a681e3395473336fcc3aa3c25dfa921f7dc254dcf01eed8662f430f1fee200d", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=db341e4c9d5361b07b6bd43c2d6906c0392a905a", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/client.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "802cbf1c09d2c53637d93f8beeb8974d92015f8fd82f56718b4f58c49ffbfd90", - "review_fingerprint": "802cbf1c09d2c53637d93f8beeb8974d92015f8fd82f56718b4f58c49ffbfd90", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=802cbf1c09d2c53637d93f8beeb8974d92015f8fd82f56718b4f58c49ffbfd90", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=0e8efec58e6bfd54f21a79a54400a29d3621ec57", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/ent.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "e1884d8db16560f0e2dbd1793b6005c3b8a690ab09773a8fd0ebf4a537e5cc25", - "review_fingerprint": "e1884d8db16560f0e2dbd1793b6005c3b8a690ab09773a8fd0ebf4a537e5cc25", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=e1884d8db16560f0e2dbd1793b6005c3b8a690ab09773a8fd0ebf4a537e5cc25", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=29f3f0d68fb4f58cb2487cf43419e5679d1a23e2", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/group.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "099ecd13b122498e1ad492474fc906af526a0112fc408d29f69f3f408a2ea3bd", - "review_fingerprint": "099ecd13b122498e1ad492474fc906af526a0112fc408d29f69f3f408a2ea3bd", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=099ecd13b122498e1ad492474fc906af526a0112fc408d29f69f3f408a2ea3bd", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=5510c5aa1a70019d12d0af6f2fcff36fc82bd082", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/group/group.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "b07b3863c33938f8b47523e5d06e4a69e2e90245bbed59f5b8351a0840867d32", - "review_fingerprint": "b07b3863c33938f8b47523e5d06e4a69e2e90245bbed59f5b8351a0840867d32", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=b07b3863c33938f8b47523e5d06e4a69e2e90245bbed59f5b8351a0840867d32", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=66dbdc412de8a1c7208dbde09b408a35dd64b791", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/group/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "76968df304d4c833f009ce920973a0cce8c620443c5aa57c68134f4921a97951", - "review_fingerprint": "76968df304d4c833f009ce920973a0cce8c620443c5aa57c68134f4921a97951", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=76968df304d4c833f009ce920973a0cce8c620443c5aa57c68134f4921a97951", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=149f2da8a083852618dfb00cb189215eeeebb6bd", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/group_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "7913ca496981727baff37e9ad79e9d96fccc005106cf24fa8ed1fae8ba4c4d40", - "review_fingerprint": "7913ca496981727baff37e9ad79e9d96fccc005106cf24fa8ed1fae8ba4c4d40", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=7913ca496981727baff37e9ad79e9d96fccc005106cf24fa8ed1fae8ba4c4d40", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=7f4c6507088d7c6fcf1efd988083f08fb1547247", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/group_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "cc0ee818e43a839e91d49197949217874750a6e88c41fecf0ecc2eb3eeeab114", - "review_fingerprint": "cc0ee818e43a839e91d49197949217874750a6e88c41fecf0ecc2eb3eeeab114", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=cc0ee818e43a839e91d49197949217874750a6e88c41fecf0ecc2eb3eeeab114", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=091466452f861afd34abb190c6eb16b02a2a82b2", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/hook/hook.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "f5606ebfd962399ee9e1b26c541d5545c58176851f8a92408d3cb7b08d0bc945", - "review_fingerprint": "f5606ebfd962399ee9e1b26c541d5545c58176851f8a92408d3cb7b08d0bc945", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=f5606ebfd962399ee9e1b26c541d5545c58176851f8a92408d3cb7b08d0bc945", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=f3beb5b644cddc5e4c5a938fbfd3e95838e908d2", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/intercept/intercept.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "6b5a1ccb89fb92bda5bf9e668682bb8764fd606264e295dcbe3c4913ed037ae9", - "review_fingerprint": "6b5a1ccb89fb92bda5bf9e668682bb8764fd606264e295dcbe3c4913ed037ae9", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=6b5a1ccb89fb92bda5bf9e668682bb8764fd606264e295dcbe3c4913ed037ae9", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=5a6bd40cfe5ba01f24c80dad2a75e4524fdf0962", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/migrate/schema.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "10bb6ce66cc45c2d5b17e9ac34b9244d46594ad86e55357236e95b7c0aa1e043", - "review_fingerprint": "10bb6ce66cc45c2d5b17e9ac34b9244d46594ad86e55357236e95b7c0aa1e043", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=10bb6ce66cc45c2d5b17e9ac34b9244d46594ad86e55357236e95b7c0aa1e043", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=ceefcc684f77aa8b02c7f1c4dea99b259c0fbe28", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/mutation.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "0c928c8ecd04142397fb47d84341150e63a802d33a002da5850a865d8f905512", - "review_fingerprint": "0c928c8ecd04142397fb47d84341150e63a802d33a002da5850a865d8f905512", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=0c928c8ecd04142397fb47d84341150e63a802d33a002da5850a865d8f905512", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=3367fab567d6818f98e9bb725bab4420e88016eb", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/predicate/predicate.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "47e3e2282c5c748a1566477a99adb454c8372d9dd64f1add58f49f63b503d715", - "review_fingerprint": "47e3e2282c5c748a1566477a99adb454c8372d9dd64f1add58f49f63b503d715", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=47e3e2282c5c748a1566477a99adb454c8372d9dd64f1add58f49f63b503d715", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=f8b33fe366ebb24decb26e403bb9e3cbb6994bf6", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/runtime/runtime.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "f3465976aa44da7b2e3b30d5a7464fe4c8a2fa06a3eafe61d55ab5bef9ed3bce", - "review_fingerprint": "f3465976aa44da7b2e3b30d5a7464fe4c8a2fa06a3eafe61d55ab5bef9ed3bce", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=f3465976aa44da7b2e3b30d5a7464fe4c8a2fa06a3eafe61d55ab5bef9ed3bce", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=5a718fabcac8cc3881118679fc14b7a58ec28b71", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/schema/account.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "7e13df6e195dcca9580db02ac3a6c5e6d8d233a34553235d90e9fa563a4f5625", - "review_fingerprint": "7e13df6e195dcca9580db02ac3a6c5e6d8d233a34553235d90e9fa563a4f5625", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "accounts 表的 ent schema(字段/边/索引)。下游相对上游新增:wire_platform、provider_profile(Cindy 供应商身份与调度池隔离,含复合索引 platform+wire_platform+provider_profile);management_folder_id 及 management_folder 边、tags 多对多边(account-tools 的目录/标签分类,注释明确“never used by scheduling or billing”);cindy_balance_insufficient_at、cindy_banned_at、cindy_credential_generation(Cindy 余额耗尽/401 终态/凭证代数投影)。这些只是持久化列定义,判定这些状态的业务规则在 service/cindy_* 与 plugins/cindy-provider、account-tools(其他切片);ent schema 只能由宿主持有,故归 core-data-and-migrations。已核对每个新列都有对应 SQL 迁移(192/202/229-231/237)。静态阅读,未生成代码、未连库。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "git diff aea725f: +L67-L76 wire_platform(MaxLen50,Default\"\")/provider_profile(MaxLen100,Default\"\");+L107-L110 management_folder_id Optional Nillable;+L164-L177 cindy_balance_insufficient_at/cindy_banned_at(timestamptz Nillable)/cindy_credential_generation(Int64 Default0 NonNegative);+L243-L248 edge.From(management_folder, AccountFolder).Ref(accounts).Field(management_folder_id).Unique 与 edge.To(tags, AccountTag).Through(account_tag_bindings, AccountTagBinding);+L272/L276 两个索引。其余字段(proxy_fallback_origin_id、parent_account_id/quota_dimension spark 影子、session_window_*、temp_unschedulable_*)与上游一致。", - "迁移对照(rg backend/migrations): wire_platform/provider_profile → 229_cindy_platform_wire_identity.sql 等;management_folder_id → 192_codexrip_account_taxonomy.sql;cindy_balance_insufficient_at → 202_add_cindy_balance_insufficient_at.sql;cindy_banned_at/cindy_credential_generation → 237_cindy_terminal_health_and_cleanup.sql。", - "消费方计数(非测试 go 文件, backend/internal+plugins): WirePlatform 17、ProviderProfile 20、CindyBannedAt 11、CindyBalanceInsufficientAt 13、CindyCredentialGeneration 6、ManagementFolderID 6。最后修改提交 d3261a58b/9e252c389/adbe56c91/900a5a516 (Cindy 系列)。", - "未宣称:未运行 ent generate 校验生成代码同步;未评价 cindy_* 列上的业务判定逻辑归属(属 service/cindy_* 切片)。" - ] - }, - { - "path": "backend/ent/schema/account_folder.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "293a50defc4fd0241556f44a99b96b0072cb51fbdb7aa9b0456e026eaf4a9f23", - "review_fingerprint": "293a50defc4fd0241556f44a99b96b0072cb51fbdb7aa9b0456e026eaf4a9f23", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增 ent schema(上游无此文件,来自 864a4b403 cockpit 账号控制台):account_folders 表,字段 name(≤100)/normalized_name(≤100, Unique)/sort_order(Default 0),TimeMixin 时间戳,edge.To(accounts) 带 OnDelete Restrict(有账号归属的目录不可删),索引 (sort_order, name)。注释明确这是仅供管理分类的平铺目录,不被调度/计费/鉴权/模型路由读取。与迁移 192_codexrip_account_taxonomy.sql 的建表语句(UNIQUE normalized_name、FK ON DELETE RESTRICT、idx_account_folders_sort_name)逐项一致。目录管理的业务逻辑在 service/admin_account_taxonomy.go(其他切片),此处仅为持久化定义,归宿主数据层。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "L28-L34 Fields: name/normalized_name(Unique)/sort_order;L36-L41 Edges: edge.To(\"accounts\", Account.Type).Annotations(entsql.OnDelete(entsql.Restrict));L43-L45 index.Fields(\"sort_order\",\"name\")。对应 account.go:243-246 的反向边 management_folder。", - "git ls-tree aea725f 为空 → 整文件即下游增量;提交 864a4b403 (2026-07-29)。迁移对照 backend/migrations/192_codexrip_account_taxonomy.sql:3-10 建表、:21-33 fk_accounts_management_folder_id ON DELETE RESTRICT、:53-54 索引。", - "消费方(非测试): 仅 backend/internal/service/admin_account_taxonomy.go 直接使用 ent.AccountFolder。未宣称:未运行 ent generate,未评价 taxonomy service 是否应迁入 account-tools 插件。" - ] - }, - { - "path": "backend/ent/schema/account_tag.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "f6c216b2cc844d177694a5581f40d0dd54cd4bd162fce1f948ad86e296621b20", - "review_fingerprint": "f6c216b2cc844d177694a5581f40d0dd54cd4bd162fce1f948ad86e296621b20", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增 ent schema(上游无):account_tags 表,字段与 account_folder 同构(name/normalized_name Unique/sort_order),TimeMixin,反向边 edge.From(accounts).Ref(tags).Through(account_tag_bindings, AccountTagBinding) 构成显式多对多,索引 (sort_order, name)。仅为管理标签的持久化定义,与迁移 192 的 account_tags 建表及 idx_account_tags_sort_name 一致;标签业务逻辑在 service/admin_account_taxonomy.go。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "L27-L33 Fields;L35-L41 edge.From(\"accounts\", Account.Type).Ref(\"tags\").Through(\"account_tag_bindings\", AccountTagBinding.Type),与 account.go:247-248 edge.To(\"tags\") 配对;L43-L45 索引。", - "git ls-tree aea725f 为空;提交 864a4b403。迁移对照 192_codexrip_account_taxonomy.sql:12-19 建表、:55-56 索引。", - "未宣称:未运行 ent generate;未评价管理标签功能的插件归属。" - ] - }, - { - "path": "backend/ent/schema/account_tag_binding.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "d9b0d5cdbeaaccc3785cd33b782c596e61ecc023401eeaccf7c0883318ea60b7", - "review_fingerprint": "d9b0d5cdbeaaccc3785cd33b782c596e61ecc023401eeaccf7c0883318ea60b7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增 ent schema(上游无):account_tag_bindings 显式中间表,复合主键 field.ID(account_id, tag_id),字段 account_id/tag_id Int64 与 Immutable created_at(timestamptz, Default time.Now),两条 Required Unique 边分别指向 Account 与 AccountTag 且 OnDelete Cascade(删账号或删标签自动清绑定),索引 tag_id。与迁移 192 的 PRIMARY KEY (account_id, tag_id)、两处 REFERENCES ... ON DELETE CASCADE、idx_account_tag_bindings_tag_id 一致。纯持久化定义,归宿主数据层。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "L21-L26 Annotations: Table account_tag_bindings + field.ID(\"account_id\",\"tag_id\");L28-L37 Fields;L39-L48 edge.To(account).Unique().Required().Field(account_id) / edge.To(tag)...Field(tag_id),均 entsql.OnDelete(entsql.Cascade);L50-L52 index tag_id。", - "git ls-tree aea725f 为空;提交 864a4b403。迁移对照 192_codexrip_account_taxonomy.sql:36-41 建表(CASCADE + 复合 PK)、:57-58 索引。", - "未宣称:未运行 ent generate。" - ] - }, - { - "path": "backend/ent/schema/api_key.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "b057165b31cfdb824396fd8366c9dec09d1ca70a9af804c008e14c532b81b0c9", - "review_fingerprint": "b057165b31cfdb824396fd8366c9dec09d1ca70a9af804c008e14c532b81b0c9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "api_keys 表 ent schema。下游相对上游新增 purpose(MaxLen32,Default \"user\",内部生命周期用途)与 lease_id(MaxLen64,Optional Nillable Unique,短时内部租约幂等标识)两列及 purpose、(purpose, expires_at) 两个索引,来自 bb8a63c02“lease ephemeral release acceptance API keys”(迁移 239_codexrip_release_acceptance_api_key_leases.sql,244/245 codex ticket 迁移亦引用 lease_id)。其余 quota/rate_limit_5h-7d/window_* 字段、user/group/usage_logs 边与上游一致。repository/api_key_repo.go 用 PurposeEQ(APIKeyPurposeUser) 把内部租约 key 从用户可见列表/计数中过滤,SetNillableLeaseID 写入租约;租约业务在 service/api_key.go(其他切片)。持久化列定义归宿主数据层。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "git diff aea725f: +L50-L59 field.String(\"purpose\").MaxLen(32).Default(\"user\") 与 field.String(\"lease_id\").MaxLen(64).Optional().Nillable().Unique();+L152-L153 index.Fields(\"purpose\")、index.Fields(\"purpose\",\"expires_at\")。L34-L128 其余字段、L131-L144 边、L146-L159 其他索引与上游相同。", - "调用链: repository/api_key_repo.go:45 activeQuery().Where(apikey.PurposeEQ(service.APIKeyPurposeUser));:59 SetNillableLeaseID;:63-64 SetPurpose;:633/:746/:761 用户维度列表与计数均排除非 user purpose;service/api_key.go 为唯一非测试服务侧调用方。迁移: 239_codexrip_release_acceptance_api_key_leases.sql(含 release_acceptance_api_key_lease_migration_test.go)。", - "观察: lease_id Unique 在 ent 层为全局唯一(含软删除行),与“幂等标识”语义一致;(purpose, expires_at) 索引服务于过期租约清扫查询。未宣称:未运行 ent generate,未评价租约发放/回收逻辑正确性。" - ] - }, - { - "path": "backend/ent/schema/group.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "a278b1f78ad0e0887677d390ba60f76af6cb419937fd2ab41ff7d53afda76b40", - "review_fingerprint": "a278b1f78ad0e0887677d390ba60f76af6cb419937fd2ab41ff7d53afda76b40", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "groups 表 ent schema,346 行,含计费倍率/高峰倍率、订阅限额、图片与视频定价、搜索与语音定价、model_pricing、Claude Code 限制与降级分组、模型路由、OpenAI Messages 调度配置、模型白名单、Codex manifest 配置、RPM 上限、推理强度上限与映射、利润控制等大量字段,以及 api_keys/redeem_codes/subscriptions/usage_logs/accounts/allowed_users 边和 duplicate_operation_id 部分唯一索引。下游相对上游 aea725f 的差异仅 6 行:在 platform 之后新增 wire_platform(MaxLen50, Default \"\") 与 provider_profile(MaxLen100, Default \"\"),与 account.go 同源(Cindy 供应商身份/调度池隔离,迁移 229_cindy_platform_wire_identity.sql)。其余全部字段为上游 v0.2.7 既有内容。只是持久化列定义,判定 wire/profile 的业务规则在 service/cindy_* 与 plugins/cindy-provider(其他切片)。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "git diff aea725f: 仅 +L82-L87 wire_platform/provider_profile 两字段;L36-L312 其余 Fields、L315-L330 Edges、L332-L346 Indexes(含 idx_groups_duplicate_operation_id_active 部分索引)与上游一致。", - "迁移对照: rg backend/migrations 显示 wire_platform/provider_profile 由 229_cindy_platform_wire_identity.sql、234/235/236/252 系列维护(含 groups 表投影修复 234_fix_cindy_platform_projection_round_trip.sql)。消费方计数(非测试 go): WirePlatform 17、ProviderProfile 20 处。", - "最后修改提交 cc33df048/581a88211(2026-09-10/08)及上游 v0.2.1/v0.2.2 合并。未宣称:未运行 ent generate,未评价 Cindy 分组身份规则的插件归属。" - ] - }, - { - "path": "backend/ent/schema/system_prompt_runtime.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "cb2de0a089c78a78a403db368785734dbb09fb7d09b1a3cd214da6d54e467c81", - "review_fingerprint": "cb2de0a089c78a78a403db368785734dbb09fb7d09b1a3cd214da6d54e467c81", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增 ent schema(上游无,d89d7b20e 业务系统提示词管理):system_prompt_runtime 单例全局激活策略表,字段 enabled/expose_server_prompt/compact_enabled 三开关、active_template_id/active_version_id 可空外键、revision(Default 1)、updated_by、updated_at(UpdateDefault),两条 Unique 边指向 SystemPromptTemplate/SystemPromptTemplateVersion 且 OnDelete Restrict。单例约束(id SMALLINT DEFAULT 1 CHECK(id=1))、revision>0 与 active_template/active_version 成对非空的 CHECK 均只在迁移 194_business_system_prompts.sql 中,ent 侧不表达,属已知的 schema/SQL 分工。这是 prompt-skills 领域数据的持久化定义,业务规则在 service/business_system_prompt_service.go 与 plugins/prompt-skills(其他切片);ent schema 只能由宿主持有。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "L22-L33 Fields(无 Mixin,自管 updated_at);L35-L46 edge.To(active_template).Field(active_template_id).Unique().OnDelete(Restrict) 与 edge.To(active_version)...同。git ls-tree aea725f 为空。", - "迁移对照 194_business_system_prompts.sql:38-52: id SMALLINT PRIMARY KEY DEFAULT 1、CHECK (id = 1)、revision CHECK (>0)、CONSTRAINT system_prompt_runtime_active_pair 成对约束;schema 未声明这些 CHECK,依赖 SQL 迁移。", - "消费方(非测试): repository/business_system_prompt_repository.go、service/business_system_prompt_service.go、handler/admin/system_prompt_handler.go;plugins/prompt-skills/registry/support.go 亦引用系统提示词概念。未宣称:未运行 ent generate,未评价 service 与 prompt-skills 插件是否重复执行激活策略。" - ] - }, - { - "path": "backend/ent/schema/system_prompt_template.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "c83ea740b06bb0fa3191a6ff1a130355f62547b64bb6c96e076e1b3d6d8db66a", - "review_fingerprint": "c83ea740b06bb0fa3191a6ff1a130355f62547b64bb6c96e076e1b3d6d8db66a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增 ent schema(上游无):system_prompt_templates 管理员维护的业务提示词模板表,TimeMixin+SoftDeleteMixin,字段 slug(≤100 Unique)/name(≤200)/description(text Default \"\")/is_seed/managed_source(≤100 可空,6a46609da 上游同步新增)/created_by/updated_by,边 versions→SystemPromptTemplateVersion OnDelete Restrict(有版本的模板不可硬删)。注意 slug Unique 为全局唯一含软删除行,软删后同 slug 不能重建(与 group.name 用部分索引的做法不同),这是设计取舍而非缺陷。持久化定义归宿主数据层,模板业务在 service/business_system_prompt_service.go。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "L23-L25 Mixin TimeMixin+SoftDeleteMixin;L27-L37 Fields(slug Unique、managed_source Nillable);L39-L44 edge.To(versions).OnDelete(Restrict)。git ls-tree aea725f 为空;提交 d89d7b20e/6a46609da。", - "迁移对照: 194_business_system_prompts.sql 建表;199_business_system_prompt_managed_source.sql 增加 managed_source;200/201 远程 skill 源迁移。消费方同 system_prompt_runtime.go。", - "未宣称:未运行 ent generate;未评价模板管理 API 的插件归属。" - ] - }, - { - "path": "backend/ent/schema/system_prompt_template_version.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "9ff1cfd1bcc9b8b3942993bbb1b540786d837ecf2f4bd138481d5b3437d11d78", - "review_fingerprint": "9ff1cfd1bcc9b8b3942993bbb1b540786d837ecf2f4bd138481d5b3437d11d78", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增 ent schema(上游无):system_prompt_template_versions 不可变版本表,字段 template_id/version、body(text NotEmpty)、sha256(Min/MaxLen 64)、byte_length Range(1,65536)、composition_mode(Default inline)/bundle_id/bundle_manifest_sha256(离线 skill bundle,迁移 195)、note、source_repository/commit/version/artifact/artifact_sha256/license_sha256(上游同步溯源,196/198/200)、created_by、published_at/published_by、Immutable created_at,边 template Required Unique,唯一索引 (template_id, version)。ent 层 Range/MinLen 校验与迁移 195 的 composition_mode IN ('inline','offline_bundle') CHECK 分工互补。持久化定义归宿主数据层;版本发布规则在 service/business_system_prompt_service.go 与 prompt-skills 插件。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "L24-L46 Fields(sha256 MaxLen(64).MinLen(64)、byte_length Range(1,65536)、source_commit MaxLen 40);L48-L56 edge.From(template).Ref(versions).Field(template_id).Unique().Required();L58-L60 index.Fields(template_id, version).Unique()。git ls-tree aea725f 为空;提交 da04f5db7/6a46609da。", - "迁移对照: 195_business_system_prompt_skill_bundles.sql:6-10 composition_mode/bundle_manifest_sha256 CHAR(64)、:36-38 CHECK composition_mode IN ('inline','offline_bundle');196/198/200/201 source_* 与远程 skill 列。", - "观察: source_artifact_sha256/source_license_sha256 仅 MaxLen(64) 无 MinLen,与 sha256/bundle_manifest_sha256 的严格 64 位不一致,但为可空溯源字段,非阻塞。未宣称:未运行 ent generate。" - ] - }, - { - "path": "backend/ent/schema/user_platform_quota.go", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "c99e94aaaf1540efa9b9f3ec840d7c32a68828ab92a24db02a10534d38c31273", - "review_fingerprint": "c99e94aaaf1540efa9b9f3ec840d7c32a68828ab92a24db02a10534d38c31273", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "user_platform_quotas 表 ent schema:按用户×平台的日/周/月 USD 限额与已用量、窗口起点,软删除友好的 (user_id, platform) 部分唯一索引。下游相对上游 aea725f 的唯一差异是 platform 字段 Validate 白名单在 minimax 与 opencode_go 之间加入 \"cindy\"(Cindy 作为一等计费平台,提交链 242907854/cc8cc870c)。已核对三处需保持同步的权威源:service/domain_constants.go:128 AllowedQuotaPlatforms 含 PlatformCindy;DB CHECK 约束经 237_user_platform_quotas_add_cindy → 241 → 251_user_platform_quota_platform_union 按文件名排序(migrations_runner.go:186 sort.Strings)最终为 11 个平台的并集,与此处 Validate 列表逐项一致(中间态 237_cindy 与 241 曾缺 opencode_go,已被 251 修复,属其他切片)。列定义与校验属宿主配额数据层,配额判定逻辑在 service(core-quota-and-protocol)。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "git diff aea725f: 仅 L44-L45 case 列表 +\"cindy\"。L34-L94 其余字段(decimal(20,10) 限额/用量、timestamptz 窗口起点)、L96-L104 user 边、L106-L113 IndexWhere(\"deleted_at IS NULL\") 部分唯一索引与上游一致。", - "同步核对: service/domain_constants.go:128-140 AllowedQuotaPlatforms = [anthropic, openai, gemini, antigravity, grok, kimi, zhipu, deepseek, cindy, minimax, opencode_go];backend/migrations/251_user_platform_quota_platform_union.sql:10-12 CHECK (platform IN (... 'minimax','cindy','opencode_go'));两者与 L44-L45 的 11 个字面量集合相同。", - "迁移顺序依据: repository/migrations_runner.go:186 sort.Strings(files);237_add_minimax_platform.sql 与 237_user_platform_quotas_add_cindy.sql 同号不同名,均早于 238/241/251。未宣称:未连库验证约束现状,未运行 ent generate。" - ] - }, - { - "path": "backend/ent/schema/user_platform_quota_cindy_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5e68a8c3155179bd31d7bdb71f9c1e689e0566a945fab166aa3bba86c96c4358", - "review_fingerprint": "5e68a8c3155179bd31d7bdb71f9c1e689e0566a945fab166aa3bba86c96c4358", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "全文静态审查unit fixture:导入Ent runtime后验证真正生成入口PlatformValidator非空,接受canonical Cindy及列举的10个平台,拒绝空串/大小写变体/unknown。没有DB、网络或生成操作。该文件的旧AllExistingPlatforms方法未枚举后来增加的opencode_go,不把方法名当作11平台全覆盖或运行通过证据。", - "evidence": [ - "artifacts/evidence/v027-schema-constraints-review.json", - "TestUserPlatformQuotaValidatorAllowsCanonicalCindy and TestUserPlatformQuotaValidatorAllowsMiniMaxAndAllExistingPlatforms; exact current source read.", - "No test execution in this review; current 11-platform schema equality was separately checked against domain_constants.go and migration251." - ] - }, - { - "path": "backend/ent/systempromptruntime.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "e89c78d17b8078a12fa673ca1b98d972f1f9b0ba568a8c76051d269d22630d70", - "review_fingerprint": "e89c78d17b8078a12fa673ca1b98d972f1f9b0ba568a8c76051d269d22630d70", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=e89c78d17b8078a12fa673ca1b98d972f1f9b0ba568a8c76051d269d22630d70", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systempromptruntime/systempromptruntime.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "3f6623db82d75ac22a8ddbfcba72f877d7f393065465ed7ddcc2ca8420e3a679", - "review_fingerprint": "3f6623db82d75ac22a8ddbfcba72f877d7f393065465ed7ddcc2ca8420e3a679", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=3f6623db82d75ac22a8ddbfcba72f877d7f393065465ed7ddcc2ca8420e3a679", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systempromptruntime/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "5f74a9ec49bbd96cea1dfa4185cdf2d096716d5d28bd41fbad063e74c58ebe7e", - "review_fingerprint": "5f74a9ec49bbd96cea1dfa4185cdf2d096716d5d28bd41fbad063e74c58ebe7e", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=5f74a9ec49bbd96cea1dfa4185cdf2d096716d5d28bd41fbad063e74c58ebe7e", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systempromptruntime_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "6c24b42e456c2d8dfe41dcbc5547dde1a79f0fdbff816f637806398bb2b1656d", - "review_fingerprint": "6c24b42e456c2d8dfe41dcbc5547dde1a79f0fdbff816f637806398bb2b1656d", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=6c24b42e456c2d8dfe41dcbc5547dde1a79f0fdbff816f637806398bb2b1656d", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systempromptruntime_delete.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "0fe9d1419cb26d29943ccb5fe09af2edccb62850a4c72163b0ada9bd42031017", - "review_fingerprint": "0fe9d1419cb26d29943ccb5fe09af2edccb62850a4c72163b0ada9bd42031017", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=0fe9d1419cb26d29943ccb5fe09af2edccb62850a4c72163b0ada9bd42031017", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systempromptruntime_query.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "f1b1c4b96910e4d92908994432985d61695d0478a7f3846ff067a74fc0e52559", - "review_fingerprint": "f1b1c4b96910e4d92908994432985d61695d0478a7f3846ff067a74fc0e52559", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=f1b1c4b96910e4d92908994432985d61695d0478a7f3846ff067a74fc0e52559", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systempromptruntime_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "c34c2d2c48db4746bde0678df433e52ce3210108823ee75493b243193c0dc79c", - "review_fingerprint": "c34c2d2c48db4746bde0678df433e52ce3210108823ee75493b243193c0dc79c", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=c34c2d2c48db4746bde0678df433e52ce3210108823ee75493b243193c0dc79c", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplate.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "0513118895f84f36530269ecb8598eb54ec9ca712c3767c64e9f666bb2fe9ea4", - "review_fingerprint": "0513118895f84f36530269ecb8598eb54ec9ca712c3767c64e9f666bb2fe9ea4", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=0513118895f84f36530269ecb8598eb54ec9ca712c3767c64e9f666bb2fe9ea4", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplate/systemprompttemplate.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "cca0fde70984d8c8741b6c110c06883b05c895d4b95820bf538cfc32e7abbf5f", - "review_fingerprint": "cca0fde70984d8c8741b6c110c06883b05c895d4b95820bf538cfc32e7abbf5f", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=cca0fde70984d8c8741b6c110c06883b05c895d4b95820bf538cfc32e7abbf5f", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplate/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "0be1b0f09f51ec4be7643bf9bbd5942883f83cfa4166dcdc7a3010b7456a9d3d", - "review_fingerprint": "0be1b0f09f51ec4be7643bf9bbd5942883f83cfa4166dcdc7a3010b7456a9d3d", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=0be1b0f09f51ec4be7643bf9bbd5942883f83cfa4166dcdc7a3010b7456a9d3d", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplate_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "fd0f2d212d6f008745daeb99a839041bf6d29ebff3c1123e7a27304ff6e54137", - "review_fingerprint": "fd0f2d212d6f008745daeb99a839041bf6d29ebff3c1123e7a27304ff6e54137", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=fd0f2d212d6f008745daeb99a839041bf6d29ebff3c1123e7a27304ff6e54137", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplate_delete.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "da956d8f52618f6e22f3813850694707046e8ab89f7530af5cecce3e91406fe1", - "review_fingerprint": "da956d8f52618f6e22f3813850694707046e8ab89f7530af5cecce3e91406fe1", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=da956d8f52618f6e22f3813850694707046e8ab89f7530af5cecce3e91406fe1", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplate_query.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "1785c0c1f6f3dff4608128feb812c1e4d5f56c70600e744b08b03be8063ced22", - "review_fingerprint": "1785c0c1f6f3dff4608128feb812c1e4d5f56c70600e744b08b03be8063ced22", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=1785c0c1f6f3dff4608128feb812c1e4d5f56c70600e744b08b03be8063ced22", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplate_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "9bc725c762d33067fb87b0c2d60664c2d4c8cbfd38638fa49e730fe3db3ac7c8", - "review_fingerprint": "9bc725c762d33067fb87b0c2d60664c2d4c8cbfd38638fa49e730fe3db3ac7c8", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=9bc725c762d33067fb87b0c2d60664c2d4c8cbfd38638fa49e730fe3db3ac7c8", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplateversion.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "0ea0b7be02bd1ff1dbcd1a3c4c1196e7b59028708e6e478e83773a6b94381fdb", - "review_fingerprint": "0ea0b7be02bd1ff1dbcd1a3c4c1196e7b59028708e6e478e83773a6b94381fdb", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=0ea0b7be02bd1ff1dbcd1a3c4c1196e7b59028708e6e478e83773a6b94381fdb", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplateversion/systemprompttemplateversion.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "d60ff63364d37c24316ed04bff2a7158d9093bd041bb231e889af1f00347cbc7", - "review_fingerprint": "d60ff63364d37c24316ed04bff2a7158d9093bd041bb231e889af1f00347cbc7", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=d60ff63364d37c24316ed04bff2a7158d9093bd041bb231e889af1f00347cbc7", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplateversion/where.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "73b7c1acc670ad62a467abb5b12555d3079bb9dd8188d4d71c476f549d5831ae", - "review_fingerprint": "73b7c1acc670ad62a467abb5b12555d3079bb9dd8188d4d71c476f549d5831ae", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=73b7c1acc670ad62a467abb5b12555d3079bb9dd8188d4d71c476f549d5831ae", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplateversion_create.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "33acc63c415fc3a934179b6a51c734cbe8599f2abcf02e2e66e23001eb8afde8", - "review_fingerprint": "33acc63c415fc3a934179b6a51c734cbe8599f2abcf02e2e66e23001eb8afde8", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=33acc63c415fc3a934179b6a51c734cbe8599f2abcf02e2e66e23001eb8afde8", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplateversion_delete.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "c4a566a714ac937879da416d3b52bc85391aea9e97716d5989c9bbf77609e2d1", - "review_fingerprint": "c4a566a714ac937879da416d3b52bc85391aea9e97716d5989c9bbf77609e2d1", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=c4a566a714ac937879da416d3b52bc85391aea9e97716d5989c9bbf77609e2d1", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplateversion_query.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "b6d68007d6935a7f92547dd6464ebdd4a909d56c34570a4ccb3a96c58d752770", - "review_fingerprint": "b6d68007d6935a7f92547dd6464ebdd4a909d56c34570a4ccb3a96c58d752770", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=b6d68007d6935a7f92547dd6464ebdd4a909d56c34570a4ccb3a96c58d752770", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/systemprompttemplateversion_update.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "7a0a94b6a77c74681bf720ead717dd1963c9d14bbcc8cb58a93b0db6145a8c94", - "review_fingerprint": "7a0a94b6a77c74681bf720ead717dd1963c9d14bbcc8cb58a93b0db6145a8c94", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=7a0a94b6a77c74681bf720ead717dd1963c9d14bbcc8cb58a93b0db6145a8c94", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=absent", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/ent/tx.go", - "candidate_owner": "mixed-requires-review", - "role": "generated", - "present": true, - "content_sha256": "88f3c53a260bbe4f75e7a898c7e4ea3849083da1a570cbc78643caf5a52e90a2", - "review_fingerprint": "88f3c53a260bbe4f75e7a898c7e4ea3849083da1a570cbc78643caf5a52e90a2", - "review_status": "reviewed", - "decision": "generated-source", - "owner": "backend-ent-generator", - "reason": "Current bytes carry the Ent generated marker; the committed Ent command was rerun in isolated worktree ent-provenance-20260920 and all 67 coverage outputs matched current SHA-256. This closes generator provenance only; no semantic review is claimed.", - "evidence": [ - "current_sha256=88f3c53a260bbe4f75e7a898c7e4ea3849083da1a570cbc78643caf5a52e90a2", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=f0288403400c38d9df1808015521df7b3b969a4a", - "generator=backend/ent/generate.go#L6", - "generator_sha256=881d119de5f8a9d886f360777222cf01441ed3085e820d742357f4f0d44cc558", - "command=go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,intercept,sql/execquery,sql/lock --idtype int64 ./schema", - "source_set=backend/ent/schema/*.go; source_file_count=47; source_index_sha256=6b8f1c876ed93055b7693c9ceaf3fe337ca5a647b30565616700f3ba86a768c6", - "generated_header=Code generated by ent, DO NOT EDIT.", - "generation_reproduction=isolated worktree ent-provenance-20260920; output_sha256_match=true; output_diff=none", - "inventory_sha256_match=true" - ] - }, - { - "path": "backend/go.mod", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "817efa348ec5a9227570fcf0532f620295b54b96bc69b5c029c585b1c55c2a25", - "review_fingerprint": "817efa348ec5a9227570fcf0532f620295b54b96bc69b5c029c585b1c55c2a25", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主 Go 模块清单(238 行,module github.com/Wei-Shaw/sub2api, go 1.27.0)。下游相对上游的依赖增量有四类:(1) 七个插件模块 github.com/HTExplicit/sub2api-plugins/{modelpolicy,codexruntime,promptskills,accounttools,cindyprovider,imagetools,adminobservability} 以 v0.0.0 require 并 replace 到 ../plugins/,已逐一核对各 plugins/*/go.mod 的 module 名与 replace 左侧一致,说明宿主二进制在构建期静态链接七个插件域(与 go-plugin 进程外模型并存);(2) 新增 github.com/jackc/pgx/v5 v5.10.0 及其间接依赖 pgpassfile/pgservicefile/puddle,对应 repository/postgres_driver.go 用 pgx stdlib 替换 lib/pq 连接器(lib/pq v1.10.9 仍保留供 pq.Error 识别);(3) github.com/pmezard/go-difflib 与 golang.org/x/text 从 indirect 提升为直接依赖,分别被 service/remote_skill_prompt.go 与 pkg/extensionapi/v1/document_path.go、service/openai_refusal_recovery.go 直接 import;(4) 其余上游依赖版本未变。这是构建机制层面的宿主配置,不含业务规则。静态阅读,未执行 go mod tidy/build。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S44-backend-pkg-server-1-review.json", - "git diff aea725f: +L5-L17 七条 replace;+L20-L26 七条 v0.0.0 require;+L51 jackc/pgx/v5 v5.10.0;+L55 pmezard/go-difflib(原 indirect 行删除);+L82 golang.org/x/text v0.41.0(原 indirect 行删除);+L160-L162 jackc/pgpassfile、pgservicefile、puddle/v2 indirect。其余 L27-L87 直接依赖与 L90-L238 间接依赖与上游一致。", - "模块名核对: plugins/model-policy/go.mod → module github.com/HTExplicit/sub2api-plugins/modelpolicy(其余六个同样一一对应)。直接 import 核对(rg): go-difflib ← backend/internal/service/remote_skill_prompt.go;golang.org/x/text ← backend/pkg/extensionapi/v1/document_path.go、backend/internal/service/openai_refusal_recovery.go。", - "pgx 引入对应 repository/postgres_driver.go:15-26 openPostgresDB(pgx.ParseConfig + stdlib.GetConnector) 与 cmd/cleanup-ingress-reject-logs/main.go 去掉 pq.Array;lib/pq 保留用于 ent.go isTransientDatabaseInitializationError 的 *pq.Error 分支。", - "观察: 插件模块以本地 replace 方式进入宿主构建,意味着插件域与宿主同一二进制、同一进程;该架构选择的评价属插件宿主切片,此处不下结论。最后修改提交 480ec3988/8232c3d9c/990dede9b (2026-09-20)。未宣称:未运行 go build/go mod verify。" - ] - }, - { - "path": "backend/go.sum", - "candidate_owner": "mixed-requires-review", - "role": "dependency-lock", - "present": true, - "content_sha256": "23fd0dc0c2d9314ae9af470fbbbe1c5faee806ee73322802498b6a73cb280048", - "review_fingerprint": "23fd0dc0c2d9314ae9af470fbbbe1c5faee806ee73322802498b6a73cb280048", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-backend", - "reason": "Committed dependency lock is paired with backend/go.mod and its current manifest identity. Provenance is closed only; package-manager resolution, network fetches, and dependency vulnerability scanning were intentionally not run.", - "evidence": [ - "current_sha256=23fd0dc0c2d9314ae9af470fbbbe1c5faee806ee73322802498b6a73cb280048", - "upstream_base=aea725f2ea644d5592d0bbb1d63b607efa7e200a; upstream_blob=caf01c3b6be75e2863b1a1faa329bda598e9e81f", - "paired_manifest=backend/go.mod; paired_manifest_sha256=817efa348ec5a9227570fcf0532f620295b54b96bc69b5c029c585b1c55c2a25", - "paired_manifest_identity=module github.com/Wei-Shaw/sub2api", - "inventory_sha256_match=true", - "static_scope=committed lock-to-manifest provenance only; package-manager resolution and SCA were not run" - ] - }, - { - "path": "backend/internal/config/config.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "da143956a4f3ff8d643d4083e4606b2918c4fd59a92cd5e4d2c6b08c225fde5d", - "review_fingerprint": "da143956a4f3ff8d643d4083e4606b2918c4fd59a92cd5e4d2c6b08c225fde5d", - "review_status": "pending" - }, - { - "path": "backend/internal/config/config_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6e5794191362fbb50180581c075a3cfebc2c42cc6ec4c01033406d639c405e81", - "review_fingerprint": "6e5794191362fbb50180581c075a3cfebc2c42cc6ec4c01033406d639c405e81", - "review_status": "pending" - }, - { - "path": "backend/internal/config/image_studio_feature_flags.go", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "9b3fa4133b95028077472be291e7c4135882e36cbdc0d87ad29adcd8c719d100", - "review_fingerprint": "9b3fa4133b95028077472be291e7c4135882e36cbdc0d87ad29adcd8c719d100", - "review_status": "pending" - }, - { - "path": "backend/internal/domain/constants.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ee7b38b95a345045019c43a752b6e499846e8b9edb38aea52f6b25a5bf972ff0", - "review_fingerprint": "ee7b38b95a345045019c43a752b6e499846e8b9edb38aea52f6b25a5bf972ff0", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "The only downstream difference is the canonical PlatformCindy identifier used by host account/relationship invariants. Existing role/status/account mode/protocol names and official Antigravity/Bedrock default mappings are byte-unchanged in the diff; no live model availability or price assertion is made.", - "evidence": [ - "Entire constants file and exact official v0.2.7 diff read. The change is a shared identity adapter, not a second Cindy business/catalog executor.", - "artifacts/evidence/v027-lifecycle-wiring-review.json" - ] - }, - { - "path": "backend/internal/handler/admin/account_api_key_visibility.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2fb48022f8fcfa2e139879bb713663b7cf75e1d22a1c77cfa7015918b1f60048", - "review_fingerprint": "2fb48022f8fcfa2e139879bb713663b7cf75e1d22a1c77cfa7015918b1f60048", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "管理员密钥显示是宿主安全机制;完整审阅123行并补齐状态及详情/更新响应的禁止缓存头。", - "evidence": [ - "状态按已认证管理员subject.UserID隔离,进程内map由RWMutex保护;启用仍需既有专用显示密码,SHA256后常量时间比较。", - "未配置显示密码返回503、密码错误返回通用400,关闭显示仍要求管理员身份;不输出显示密码。", - "明文api_key只由详情/更新响应的buildAccountResponseWithRevealedAPIKey恢复;列表路径保持脱敏。所有相关响应现在统一Cache-Control: private, no-store和Pragma: no-cache。", - "沿admin路由、审计body脱敏和DTO恢复白名单复核:管理员鉴权/限速/审计边界保留;专用显示密码是既有额外验证约定,本审阅不把未新增TOTP视为缺陷。" - ] - }, - { - "path": "backend/internal/handler/admin/account_api_key_visibility_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b4cf9c516d5a9bfa1b75bd8ee8bfecf2f64aaeaf51bb6646f71ebc8b50371857", - "review_fingerprint": "b4cf9c516d5a9bfa1b75bd8ee8bfecf2f64aaeaf51bb6646f71ebc8b50371857", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "完整审阅206行;新增7阶段httptest禁止缓存回归已执行,其余既有测试仅静态审阅。", - "evidence": [ - "TestAPIKeyVisibilityAndRevealResponsesNeverCache实际执行status、wrong-password、enable、detail、update、disable、redacted-detail七个步骤。", - "每步断言预期状态码、private/no-store、Pragma:no-cache,响应不含配置显示密码或refresh_token;使用合成凭据及httptest recorder,无网络监听或真实模型。", - "红灯时七个步骤的Cache-Control均为空;修正后该顶层测试及全部七个步骤通过。" - ] - }, - { - "path": "backend/internal/handler/admin/account_batch_test_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5ac15c87c1c9db9871200d28353a2f0e9e389e1a54bf9df4487f5b9445d01a91", - "review_fingerprint": "5ac15c87c1c9db9871200d28353a2f0e9e389e1a54bf9df4487f5b9445d01a91", - "review_status": "reviewed", - "decision": "adapter", - "owner": "account-tools", - "reason": "批量测试宿主桥接的测试。断言:模型/推理强度选择按账号身份(TargetAccountID/metadata)而非任务序号持久化,重试恢复 normalize 后仍保持;items 与 legacy 混用、同账号不同模型/强度、空模型、非正 ID 等非法选择被拒(校验经 service.PlanBatchAccountTests 委托 account-tools 插件 fixture);BatchTestModels 仅一次 GetAccountsByIDs、101 个 ID 直接 400、目录发现受全局 5 槽并发限制(peak==5)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L21-L57 TestBatchTestSelectionsPersistByAccountIdentity: PrepareAccountJob 恢复 batchTestModelContextKey 映射,seed.Metadata 按 *seed.TargetAccountID 断言 model_id;L73-L102 reasoning_effort 逐账号持久化并经 normalize() 重跑保持。", - "L59-L71 normalize() 对 8 种混合/重复/空白选择返回错误;实际校验链 service.PlanBatchAccountTests -> testextensions fixtures.go L66-68 -> plugins/account-tools/policy/batch.go planBatch(plugin_contract_fixture_test.go init 安装 fixture)。", - "L114-L156 单次账号读取+account_not_found 行、101 ID 时 400 且不读库;L181-L233 blocking upstream 证明 5 槽全局信号量跨请求共享。", - "Static read only; no test/build execution, no production behavior verified. 新增于下游(git ls-tree aea725f 无此文件),全文即 delta。" - ] - }, - { - "path": "backend/internal/handler/admin/account_batch_testing.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "c2c45bbc9425eacda453f8de8ee95964dc5b991aa1710fbaa08cb5ab1db29bdd", - "review_fingerprint": "c2c45bbc9425eacda453f8de8ee95964dc5b991aa1710fbaa08cb5ab1db29bdd", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/account_bulk_job_scope_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a0d05c4b9ad6fc8aa307a758f86cad714ace5cf94ec6a8df71828a9131f4185a", - "review_fingerprint": "a0d05c4b9ad6fc8aa307a758f86cad714ace5cf94ec6a8df71828a9131f4185a", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "6个新增顶层:提交固定两目标后live筛选漂移与删除不换人、重放不重新查筛选/不写/不延TTL、显式ID不受filters扩展、旧targetless拒绝,含actor/kind/plugin-owner/hash隔离;全文fake依赖闭合。", - "evidence": [ - "artifacts/evidence/v027-astra-bulk-job-scope-review.json", - "Parent full-file fixture review and source SHA verification; targeted execution result reused without rerun" - ] - }, - { - "path": "backend/internal/handler/admin/account_cindy_balance.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "723befba1d3cbce1308e9a5650ffdce898bd46313ca42623f299f74a415ebaaa", - "review_fingerprint": "723befba1d3cbce1308e9a5650ffdce898bd46313ca42623f299f74a415ebaaa", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "AccountHandler 上的 5 个 Cindy 余额/封禁运维入口:ClearCindyBalanceInsufficient 解析 :id 后调 adminService,若请求经 RegisterResource 绑定了插件资源策略且带 X-Sub2API-Plugin 头则只回无凭证的 extensionv1.AccountViewRecoveryAck,否则回带运行时信息的 Account;PreviewCindyInsufficientDeletion/PreviewCindyBannedDeletion 直接透传 service 预览;DeleteCindyInsufficient/DeleteCindyBanned 经 submitCindyCleanup 只绑定 expected_count(≥0)+fingerprint(非空) 并投递 cindy_confirmed_cleanup / cindy_banned_cleanup 单条 account-job,不接受客户端 account_ids。上游 aea725f 无此文件,整文件为下游新增。业务规则(哪些账号算耗尽/封禁、指纹比对、终态 episode 清理)在 service/admin_cindy_balance.go 与 repository/account_repo_cindy_balance.go,真正删除只在宿主 account_job_execution.go L229-L260 执行一次;插件侧 manifest 仅声明 cindy.cleanup.* 资源、UI 仅调用,不存在第二执行器,故本文件是宿主到插件资源的薄适配。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Function anchors: ClearCindyBalanceInsufficient L13-L31 (id parse, service.PluginResourceBound(ctx) && X-Sub2API-Plugin header -> AccountViewRecoveryAck defined in backend/pkg/extensionapi/v1/account_view.go L125-L128, else buildAccountResponseWithRuntime); PreviewCindyInsufficientDeletion L33-L40; DeleteCindyInsufficient L42-L44; PreviewCindyBannedDeletion L46-L53; DeleteCindyBanned L55-L57; submitCindyCleanup L59-L73 binds only expected_count/fingerprint and calls submitOneAccountJob (account_job_handler.go L267).", - "Call chain: routes/admin.go L473-L480 registers the four cleanup routes through h.Admin.Plugin.RegisterResource(service.CindyCleanupResourcePolicy()) (plugin_resources.go L301: OwnerPluginKey codexrip.cindy-provider, AllAccounts, FilterPlatform cindy, api_key type); L512 registers POST /:id/cindy-balance/recover with AccountParam \"id\" so ValidateResourcePolicy checks the actual account; RegisterResource (handler/admin/plugin_resources.go L21-L88) resolves the pinned plugin owner when no header is present, binds the resource context and policy, then validates targets. Job kinds are executed once in account_job_execution.go L229-L260 mapping ErrCindyInsufficientDeleteChanged to cindy_cleanup_target_changed; plugins/cindy-provider/manifest.source.json L114-L129 only declares the cindy.cleanup.* resource names and plugins/cindy-provider/ui/src/api.ts L191 consumes them.", - "Not claimed: correctness of the SQL preview/delete fingerprint rule (repository) and the terminal-episode clearing (service) are judged in their own records; no production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/handler/admin/account_cindy_balance_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "498ac727a90dfc820863d30dc7c83ee9fd1352475300349923204cefdac7d5f1", - "review_fingerprint": "498ac727a90dfc820863d30dc7c83ee9fd1352475300349923204cefdac7d5f1", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "account_cindy_balance.go 的桥接测试:用 cindyAdminServiceStub 包装 stubAdminService 并挂接 accountJobSubmitRepository,3 个用例分别证明 (1) 封禁清理走独立的 cindy_banned_cleanup 任务、加密载荷不含客户端传入的 account_ids 且执行结果 succeeded;(2) 耗尽预览精确返回 {count, fingerprint},删除提交返回 202 且不同步删除,任务载荷只含 expected_count/fingerprint、执行时恰好调用 DeleteCindyInsufficient 一次并传入 2/abc123;(3) 服务返回 ErrCindyInsufficientDeleteChanged 时任务项失败并映射为 cindy_cleanup_target_changed。被测对象是宿主 handler 适配层与宿主 account-job 执行器(account_job_execution.go L229-L260),不涉及插件代码;上游无此文件。测试仅静态阅读、未执行,不声称其通过。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Test anchors: cindyAdminServiceStub L16-L46 (records deleteInvocationCnt/lastExpectedCount/lastFingerprint); setupCindyAccountHandlerRouter L48-L58 registers the four routes directly on gin without RegisterResource; TestCindyBannedCleanupUsesSeparateJobWithoutClientAccountIDs L60-L84 (NotContains PayloadCipher account_ids); TestCindyInsufficientDeletePreviewAndDeleteDoNotAcceptAccountIDs L86-L126 (JSONEq preview body, 202, Zero deleteInvocationCnt before execution, 1 after); TestCindyInsufficientDeleteJobFailsWhenCandidateSetChanged L128-L147 (ErrorCode cindy_cleanup_target_changed).", - "Helpers come from account_job_submit_test.go L78-L115 (attachAccountJobSubmitter, requireSubmittedAccountJob, executeSubmittedAccountJobItems, setAccountJobTestIdempotencyKey) and admin_service_stub_test.go L92 (newStubAdminService); the asserted error code constant lives in service/account_business_errors.go L16.", - "Not proven by this test: RegisterResource plugin binding, the plugin-caller AccountViewRecoveryAck branch, and the repository fingerprint comparison (routes are mounted bare in the test). Statically read only, not executed." - ] - }, - { - "path": "backend/internal/handler/admin/account_cindy_duplicates.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "b62df7ddc35254b52772d8f6fa62e6efa8dfeb0d7f107f9c3132970264f851f4", - "review_fingerprint": "b62df7ddc35254b52772d8f6fa62e6efa8dfeb0d7f107f9c3132970264f851f4", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "只读的 Cindy 重复身份清单接口 GetCindyDuplicateIdentityInventory:通过接口断言取 adminService 的 BuildCindyDuplicateIdentityInventory,服务未实现回 501,构建失败回不带内部错误文本的 500,成功返回清单;不合并、不删除、不改账号。上游 aea725f 无此文件,整文件为下游新增。分组与建议 owner 的业务决策不在宿主:service/cindy_duplicate_inventory.go 只把 strict Cindy API-key 账号规范化为脱敏指纹候选事实,经 invokeCindyManagement(\"cindy.duplicates.plan\") 交给 cindy-provider 插件(plugins/cindy-provider/catalog/management.go)决定,再校验插件返回的 ID 集合与已知身份一致;路由 admin.go L482 以 RegisterResource(cindy.duplicates) 绑定声明该资源的唯一启用插件。因此本文件是薄适配,无第二执行器。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S51-cindy-rest-T1-review.json", - "Function anchors: cindyDuplicateInventoryAdminService interface L11-L13; GetCindyDuplicateIdentityInventory L17-L29 (type assertion -> 501 'cindy duplicate inventory is unavailable'; error -> 500 generic message, no err text leaked; response.Success(inventory)).", - "Call chain: routes/admin.go L482 GET /cindy/duplicate-identity-inventory wrapped by h.Admin.Plugin.RegisterResource(ResourceGrant cindy.duplicates, provider capability, admin permission, no OwnerPluginKey) -> service.BindResourceContext (plugin_resources.go L15-L49) picks the single enabled installation declaring the grant; adminServiceImpl.BuildCindyDuplicateIdentityInventory (service/admin_cindy_duplicate_inventory.go L7-L32) lists PlatformCindy accounts, applies the bound account-view filter, then buildCindyDuplicateIdentityInventory (service/cindy_duplicate_inventory.go L17-L72) computes fingerprints via AccountCredentialFingerprint and delegates grouping to invokeCindyManagement 'cindy.duplicates.plan' declared in plugins/cindy-provider/manifest.source.json L36 and consumed by plugins/cindy-provider/ui/src/api.ts L215 (resource 'cindy.duplicates').", - "Not claimed: correctness of the plugin's grouping rule (catalog/management.go) and of the host-side plan validation are judged in their own records; no production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/handler/admin/account_codex_import.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "92a36538e811a4a55f0138d78b915919d683cc882b5253b002f7b3896a4b13e4", - "review_fingerprint": "92a36538e811a4a55f0138d78b915919d683cc882b5253b002f7b3896a4b13e4", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/account_codex_import_job_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f4213f6a4d62bbfe6bc675694e2063d2c0d93d37ca31c8a2baf5ef2859f10218", - "review_fingerprint": "f4213f6a4d62bbfe6bc675694e2063d2c0d93d37ca31c8a2baf5ef2859f10218", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "5个顶层/10子例:实际handler提交→展平ordinal→worker逐项执行,包含嵌套/JSONL/空输入、局部失败、凭据不出加密载荷、幂等与只重试失败序号/24h不延期。fake repo/cipher/upstream,没有网络或生产读取。", - "evidence": [ - "artifacts/evidence/v027-astra-account-import-job-closure-review.json", - "Parent full-file fixture review and source SHA verification; targeted execution result reused without rerun" - ] - }, - { - "path": "backend/internal/handler/admin/account_codex_import_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3d6b2891afe52a7dca0924256448cf1ae365cca4c1cd35a39b8bc8973f027087", - "review_fingerprint": "3d6b2891afe52a7dca0924256448cf1ae365cca4c1cd35a39b8bc8973f027087", - "review_status": "reviewed", - "decision": "upstream-covered", - "owner": "core", - "reason": "Codex 导入解析/身份索引/凭据合并的测试,内容与上游 v0.2.7 实质相同:断言 JSON/行混合解析与数组展开、sessionToken 只记存在不入凭据、过期 accessToken 拒绝、无 refresh_token 时按 token/请求过期时间强制自动暂停、access-only 仅用 token 指纹做身份、同团队不同成员不互相合并/去重、索引 upsert 原位替换与旧键全部清理、批量导入旧 token 不回滚新 refresh_token。下游 delta 仅 L229/L275 两个 t.Fatal 后补 return,t.Fatal 本身已终止执行,无行为差异。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "git diff aea725f 仅 +2 行(L229/L275 t.Fatal 后 return),其余 1023 行为上游内容;主体是宿主 admin Codex 导入逻辑的测试,非插件桥接。", - "L629-L886 importCodexSessions 集成断言用内存 stub 服务验证 created/updated/skipped 计数、refresh_token 保留与升级、L1002-L1025 自签 alg=none JWT 构造仅测试用。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_codex_ticket.go", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "96653a1c9b66d388e005f75f72508ad3c92730bd679aa73f3caa65d5506da63c", - "review_fingerprint": "96653a1c9b66d388e005f75f72508ad3c92730bd679aa73f3caa65d5506da63c", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "管理端 Codex 292 票据的 HTTP 适配层:/codex-tickets/policy 返回模型列表与总开关;/:id/codex-tickets/harvest 与 /codex-tickets/batch-harvest 只做 1~100 个账号、模型必须在插件配置允许集内并去重、总开关已开的前置校验,然后按 (账号,模型) 生成 AccountJob 种子投递;/:id/codex-tickets/stop 逐模型转发停止续期。上游 v0.2.7 无此文件,整文件为下游新增。采集/续期/校验的业务执行不在此处:HarvestCodexTicket/StopCodexTicketRenewal 定义于 codex_ticket_plugin.go,经 PluginManager.InvokeAdminExtension 调用 codexrip.codex-runtime 插件,故判为 codex-runtime 的宿主适配而非第二执行器。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S62-codex-ticket-T1-review.json", - "L15-L19 codexTicketHarvestRequest{account_ids,models,force};L33-L57 ticketModels 以 gateway.CodexTicketModels() 为允许集、TrimSpace 后去重、越界即报错;L64-L102 submitCodexTicketHarvest:normalizeInt64IDList 后限制 1~100,CodexTicketsEnabled 未开则 400,种子 TargetAccountID=&id、Metadata={account_id,model_id},经 submitAccountJob(AccountJobKindCodexTicketHarvest) 投递(account_job_handler.go L202-L237:actorID 来自 accountJobActorID,支持 Idempotency-Key 回放)。路由 routes/admin.go L507-L510 挂在管理端 accounts 分组。", - "L127-L150 executeCodexTicketHarvest 由 account_job_execution.go L25-L26 按 Kind 分派;目标账号取自 item.TargetAccountID(accountJobTarget L266-L272,<=0 视为 target_missing),再调用 codex_ticket_plugin.go L70-L91 HarvestCodexTicket → InvokeAdminExtension(installation.ID, id, \"harvest\");plugin_extensions.go L14-L41 把 body.account_id 强制覆写为参数 accountID,插件侧 module.go L286-L290/L414-L420 再以 HostAccountRead 读取账号并校验 Eligible——操作绑定真实 AccountID 成立。ctx.Err()!=nil 时失败项标记为 Canceled。", - "泄露检查:写入 job item metadata 的 ticket_result 为 CodexTicketResult{stage,code,success,http_status,observed_length,message,duration_ms,fingerprint,expires_at}(codex_ticket_lifecycle.go L32-L42),不含票据正文或采集代理 URL;接口响应仅 models/enabled/stopped 与 AccountJob;StopCodexTicketRenewal 失败只回固定文案。", - "观察(非阻塞,未记为 finding):L139 传入的 \"job:%d:item:%d\" 操作串在 HarvestCodexTicket L78-L80 因 jobID>0 被改写为 \"job-\",同一作业内各 (账号,模型) 项共享同一 operation_id,去重依赖插件侧按 (account,model) 的 lease;handler 内模型允许集/总开关校验与插件 harvest 的 ticket_model_invalid/ticket_disabled 属前置快速失败的重复,不改变执行归属。未执行测试或生产验证。" - ] - }, - { - "path": "backend/internal/handler/admin/account_codex_ticket_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e06133fae6ca5959a15c4839cec037986279fc17facab9b412d8434e84fb9409", - "review_fingerprint": "e06133fae6ca5959a15c4839cec037986279fc17facab9b412d8434e84fb9409", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "单个桥接测试 TestAccountResponseCodexTicketsDoesNotUseLegacySettings:把宿主遗留配置 cfg.Gateway.OpenAICodexTicket 设为 Enabled 且带模型,但不注入 codexTicketGateway,断言 OAuth 与 SetupToken 两种 OpenAI 账号经 accountResponseFromService / accountListResponseFromService 映射后 CodexTurnTickets 为空。它证明的是管理端账号 DTO 的票据状态只能来自插件网关投影(account_handler.go enrichCodexTicketStatus 仅在 codexTicketGateway 非空时调用 CodexTicketStatuses),宿主不再自行从遗留 settings/config 计算票据状态;测试主体是宿主对 codex-runtime 数据的 DTO 适配。上游无此文件。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S62-codex-ticket-T1-review.json", - "L11-L20:构造 AccountHandler{cfg} 且 codexTicketGateway 为 nil,对 AccountTypeOAuth/AccountTypeSetupToken 各断言两个映射函数输出的 CodexTurnTickets 为空(require.Empty)。", - "被测路径:account_handler.go L465-L469 enrichCodexTicketStatus 只在 h.codexTicketGateway!=nil 时写 out.CodexTurnTickets = gateway.CodexTicketStatuses(account)(codex_ticket_plugin.go L18-L20 → OpenAICodexTicketStatuses 读取 accountPluginProjection(codexrip.codex-runtime));dto/types.go L226/L412 与 mappers.go L522 仅透传该字段。", - "不宣称:未验证 gateway 非空时的正向投影内容(无此断言);测试未被执行,仅静态阅读。" - ] - }, - { - "path": "backend/internal/handler/admin/account_create_profile_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d30ede775695c989322f8eb735501fc34892666b340fc0f9c3720e80b73dfa1c", - "review_fingerprint": "d30ede775695c989322f8eb735501fc34892666b340fc0f9c3720e80b73dfa1c", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/account_data.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "931a040d7a27f0fd7141393ab8474a441a9bc8c6f997964cfd855406c636ade3", - "review_fingerprint": "931a040d7a27f0fd7141393ab8474a441a9bc8c6f997964cfd855406c636ade3", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/account_data_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1015c8f955f4c024e792dc557d5d1e7dace14b73a07ea13f64c3a9b8a41d5605", - "review_fingerprint": "1015c8f955f4c024e792dc557d5d1e7dace14b73a07ea13f64c3a9b8a41d5605", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "导出/导入处理器测试。断言:导出按设计包含代理密码与账号凭据原文(TestExportDataIncludesSecrets 同时验证 v2 头与 folder/tags/groups/status/schedulable);spark 影子被排除并透出 skipped_shadows;过滤与排序参数按 group_id 透传、ids 选择优先于过滤;导入经 executeDataImportPayload(任务路径)复用代理并跳过默认分组;新增 TestExportDataExcludesCodexTicketMaterial 证明 codex_turn_ticket/codex_harvest_proxy_url 从导出 Extra 中脱敏且不改动原 map。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "git diff aea725f:dataAccount 结构补 v2 字段、断言从空 type/version 改为 dataType/dataVersion=2、导入测试从直接 POST /accounts/data 改走 executeDataImportPayload、新增 L331-351 脱敏测试(NotContains private-ticket-blob/legacy-proxy-secret)。", - "L331-351 证明下游修复:备份导出不再携带 Codex ticket 材料与含凭据代理 URL,且 L349-350 断言原始 Extra map 未被就地清除。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_data_identity.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "015e7001d158f13a80055943e5d3a86b2633a532397385836a48e1f950173fec", - "review_fingerprint": "015e7001d158f13a80055943e5d3a86b2633a532397385836a48e1f950173fec", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "下游新增:数据导入的账号身份键派生与倒排索引(chatgpt/xai/gemini/claude 等多平台 id、provider_subject、crs/service_account、Cindy 凭据指纹),供导入 v2 计算既有账号匹配事实;label=account_id 命中时若双方 user id 均存在且不同则拒绝匹配(L220-227),Add 先 Remove 旧键防脏匹配(L239-241),影子账号不入索引(L242-244)。属宿主保留的实际 AccountID 归属判定,匹配后的 create/update/reject 决策交给 account-tools 插件 import.plan。另含 v2 字段预校验(状态归一、分类名 1..100 字符)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "git ls-tree aea725f 无此文件,全文即下游 delta;调用链:dataAccountIdentityKeys/Find 由 account_data_import_v2.go 组装 AccountImportPlanningRequest 的 Matches 事实,决策在 plugins/account-tools/policy/import.go planImport。", - "L145-159 Cindy api-key 账号以 NormalizeCredentialIdentityBaseURL+AccountCredentialFingerprint 生成 credential_fingerprint 键;L174-200 Find 去重排序返回 MatchedBy 标签。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_data_import_decision.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5a37e8ec6ef944fdb9879a69632cc51e6cca9bae1bfef86ec2fa7f6d189fdfce", - "review_fingerprint": "5a37e8ec6ef944fdb9879a69632cc51e6cca9bae1bfef86ec2fa7f6d189fdfce", - "review_status": "reviewed", - "decision": "adapter", - "owner": "account-tools", - "reason": "导入 v2 预览/决策装配层(新下游文件):宿主收集事实——既有账号身份索引、Cindy 设备属主(sha256 指纹、owners 截断 2)、目标分组 canonical/strict/是否已有成员——组装 AccountImportPlanningRequest 交 service.PlanAccountImport(account-tools 插件 import.plan)决策,再把 create/update/reject 与业务码映射回预览项。本地无接受/拒绝规则,仅 L144-148 做受限 legacy→cindy 平台投影且注释声明由插件决定可用性;Matches 截断 2 个见证即可证歧义。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L127-181 事实装配:DeviceIdentity=sha256(deviceID) 不传明文;PayloadValid=validateDataAccountV2;L174-179 identityIndex.Find 截断 2 个匹配。L182-194 决策全部来自插件 plans,消息经 service.AccountBusinessMessage 稳定文案。", - "调用链:previewDataImport ← PreviewImportData(account_data.go L328) 与 PrepareAccountJob(account_data_import_job.go L133);插件输出经 backend/internal/service/plugin_account_import.go PlanAccountImport L10-57 的宿主不变式校验。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_data_import_job.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "8256e22344e724cd4d0d65fd9df15e749666aa47902a1825625f750417ee82d7", - "review_fingerprint": "8256e22344e724cd4d0d65fd9df15e749666aa47902a1825625f750417ee82d7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "账号任务 PrepareAccountJob 钩子(新下游文件):批量测试分支经插件 test.batch 重新规范化并恢复按账号身份的模型映射;数据导入分支在准备期校验头/设置、快照既有账号与分组(目标分组用 GetGroup 权威加载 strict 标记,避免批量列表缺标记)、先行导入代理、构建分类/分组解析器与引用缓存并生成插件决策;执行期 currentDecision 按实时身份索引重判 create/update/冲突(陈旧防护),executeOne 更新前重取目标、创建前复查无匹配,提交后 recordCommittedAccount 回写索引,cleanup 释放全部状态。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L61-206 prepare:L81-86 validateDataHeader/validateDataImportRequest;L111-126 目标分组权威加载并在 nil/ID 不符时从 groupsByID 删除陈旧条目;L195-204 cleanup 置空 state 与缓存。", - "L208-239 currentDecision 与 L286-292 create 前复查为执行期陈旧防护;其 0/1/N→create/update/reject 映射与插件 planImport 重复,但同一映射被 service.PlanAccountImport L30-45 作为宿主不变式强制,见 findings(low)。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_data_import_preview_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e32c8356440bc7f31b378f4206ba9d6b13d46637bf16fb9c26b5cbcb1510af93", - "review_fingerprint": "e32c8356440bc7f31b378f4206ba9d6b13d46637bf16fb9c26b5cbcb1510af93", - "review_status": "reviewed", - "decision": "adapter", - "owner": "account-tools", - "reason": "导入预览与任务执行的桥接测试(fixture 安装真实 account-tools 策略模块)。断言:仅精确 base_url 的 legacy Cindy 投影为 canonical;canonical Cindy 必须指向 strict Cindy 目标分组(缺失/普通分组 reject,码 target_required/target_invalid);空 canonical 分组可引导、已有成员后拒绝;六种非法 api_key 形态 reject 且 legacy 不投影;目标分组查询失败上抛;预览只读、执行期以实时索引把 stale create 重判为 update(metadata action=update、mutation runner 命中账号 44);批内凭据/设备冲突确定性 reject;预览 JSON 与任务项错误不含 api_key/设备 ID/设备来源明文。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L175-203 TestDataImportPreviewAndCommitShareDecisionEngineAtExecutionTime:preview 不落库(createdAccounts 空),执行经 executeAccountJobTestItem 走任务路径。", - "L229-256/L288-312 泄漏防护断言:json.Marshal(preview/result) NotContains sk-private-preview-secret、设备 ID、私密来源与 private-key;错误消息为稳定业务文案。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_data_import_v2.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9065dbca98b539f3c9c258184d36e918e38fbeb47d6cb719dac18ca9f86b03ab", - "review_fingerprint": "9065dbca98b539f3c9c258184d36e918e38fbeb47d6cb719dac18ca9f86b03ab", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "导入 v2 宿主执行层(新下游文件):统一设置/覆盖项校验(group/proxy/concurrency/priority/rate_multiplier 数值边界、notes 模式、分类名 1..100 预检);同步 importData(任务执行的整批回退路径,account_job_execution.go L582)与任务路径共用 create/updateImportedDataAccount(名称前后缀、状态与可调度仅显式才改、Extra 经 mergeAccountUpdateExtra 合并);分组名按平台消歧、分类经 accountConsole 服务创建(命名权威在 taxonomy 服务→account-tools 插件),创建冲突时重列缓存、失败 cleanupUnused 回滚新建分类;代理导入含 backup name 反查与降级告警。引用校验优先用准备期 referenceCache。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L100-202 importData 以实时索引 0/1/N 决定失败/更新/创建(多匹配即项级失败),每次提交后回写 accountsByID 与 identityIndex;L403-428 引用校验 referenceCache/直查双路径。", - "L720-805 taxonomy 解析创建走 console 服务(服务层经插件 taxonomy.name 归一),L825-846 cleanupUnused 逆序清理,L848-888 apply 在仅改 folder 或仅改 tags 时保留另一侧现值;L558-567 mergeDataImportMaps 生产代码中无调用方,仅测试使用(见 findings,low,迁移残留)。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_data_proxy_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "329ae962c4c3f6a943deb43bf275ab56e833ad98c29c6ed28ef952d07237cc3a", - "review_fingerprint": "329ae962c4c3f6a943deb43bf275ab56e833ad98c29c6ed28ef952d07237cc3a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "代理导入兼容性测试(新下游文件)。断言:状态同步以全字段显式替换(legacy 载荷省略有效期/备份时 ClearExpiresAt/ClearBackupID=true,避免零值覆盖);任务准备期先建代理后,同批 backup_proxy_name 可反查到新建代理(ID 400),并经 ExecuteAccountJob 冒烟创建引用该代理的账号;备用代理缺失时 fallback_mode 降级为 none 且告警保留在 result.Errors。主体是宿主代理导入机制,与插件无关。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L13-79 新建/复用 × 填充/省略 四象限断言 UpdateProxyInput 的 Clear 标志与完整字段;L81-123 PrepareAccountJob 内 importDataProxies 先行执行并回填 BackupProxyID。", - "git ls-tree aea725f 无此文件,全文即下游 delta;对应实现 account_data_import_v2.go importDataProxies/dataImportProxySettings。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_data_v2_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "95b6043a6c38fc72237709f0104b36519ce7698fe2411884e5200716edef1f7f", - "review_fingerprint": "95b6043a6c38fc72237709f0104b36519ce7698fe2411884e5200716edef1f7f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "导入/导出 v2 宿主机制测试与内存 stub 服务(新下游文件)。断言:导出全量透传 cockpit 控制台过滤(platforms/statuses/plans/proxies/folder/tags/account_ids/group_id/search/排序);身份键——vertex client_email 不构成身份、Cindy 指纹对 api_key 空白差异敏感、索引更新后旧键不可再命中;v1 版本载荷仍可导入且执行期按强身份改判为 update;统一设置(前缀/并发/优先级/状态)生效且未指定项在更新时保留、Extra 合并保留既有键;分类仅在提交时创建并大小写不敏感复用、赋值失败回滚新建分类;proxy_id=0 视为直连;部分失败逐项披露。executeDataImportPayload 直接调用同步 importData 路径。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L298-325 控制台过滤透传断言;L354-391 身份键/索引行为;L393-453 v1 兼容与统一设置;L483-531 分类提交时创建与失败回滚(folders/tags 归零);L533-550 部分成功。", - "L17-288 dataV2AdminService 为内存 stub(含分页 ListAccounts、taxonomy CRUD、SetAccountTaxonomy),是本包多组导入测试的共享桩。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_duplicate_jobs.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "78744dc5a6ead79babcd45bb65b5dd1592c4feb97a8777515272612dad051934", - "review_fingerprint": "78744dc5a6ead79babcd45bb65b5dd1592c4feb97a8777515272612dad051934", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "Cindy 重复账号复核/合并处理器(新下游文件)。Review 要求 2..AccountJobBatchSize 个净化后的 ID,全部账号须为 Cindy api-key 且凭据指纹一致,产出配置评分与确认哈希(sha256 覆盖各账号 ID+UpdatedAt,任何账号变更即失效,防陈旧合并);Merge 校验 survivor/losers 上限与哈希后,合并分组并集(SkipMixedChannelCheck=true)与标签并集,再逐个删除 loser;任务以 survivor 作为 TargetAccountID 投递,实际账号绑定明确。account-tools manifest 无 duplicate 类操作,此为宿主保留的账号维护机制,非第二执行者;凭据只以指纹参与哈希,响应不含 api_key。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L42-54/L56-77 边界校验:2..AccountJobBatchSize、loser=200);L109-146 目标一次水合(getGroupCalls==1);L245-278 索引随提交更新(1 created + 1 updateInputs)。", - "L347-376 准备后代理删除→项失败且 createdAccounts 空;L421-491 recordingCindyJobMutationRunner 记录账号 ID 作用域(create 为 0,更新为目标 ID)。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_job_handler.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "924b3ebcc3487af8e6978a257439b00bafc35df6531158e1eaf61e9d6f74a046", - "review_fingerprint": "924b3ebcc3487af8e6978a257439b00bafc35df6531158e1eaf61e9d6f74a046", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/account_job_submit_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "58aa316099b43daee555d0071abc2ac8d168c7902f5ee4efb85aa36d40c0cee7", - "review_fingerprint": "58aa316099b43daee555d0071abc2ac8d168c7902f5ee4efb85aa36d40c0cee7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "任务提交测试与本包共享测试基建(新下游文件)。TestAccountJobSubmissionRetainsResourceOwnerAndRejectsSubstitution 断言:插件执行上下文(PluginInstallation ID=7)被写入任务 metadata.plugin_id;显式传入不同 owner(8) 时 403 Forbidden 且不创建任务——防止插件任务所有权被替换。其余为共享 stub:内存任务仓库(记录 CreateAccountJobParams)、明文测试加密器、attachAccountJobSubmitter 注入 actor=77、requireSubmittedAccountJob 校验 actor/kind/幂等键/请求哈希、executeSubmittedAccountJobItems 逐 seed 执行。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L18-46 所有权保持与替换拒绝断言(metadata.plugin_id==7、/wrong-owner→403、repo.created 不增长)。", - "L78-117 测试基建被 batch_test/batch_delete/long_context/mixed_channel 等多个测试文件复用,对应 account_job_handler.go submitAccountJob L186-196。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_reasoning_policy.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0d3f5f20bfb85496a0831432855f2327416c1e8b30c15c6bf62746ff77e410ee", - "review_fingerprint": "0d3f5f20bfb85496a0831432855f2327416c1e8b30c15c6bf62746ff77e410ee", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "完整审阅21行;此处只处理导入字段合并,不重建或另写推理策略。", - "evidence": [ - "克隆已有extra与传入extra,移除本次未提交的两个推理标志,让service层按其既有省略字段规则保留存储值。", - "显式提交的非boolean值继续进入严格service验证并被拒绝;存储中的旧畸形值不会由再导入隐式改为true。", - "追踪account_codex_import和account_data_import_v2调用点,并核对service/admin_account.go的preserveOmittedOpenAIReasoningPolicyExtra;未改这些下游调用。" - ] - }, - { - "path": "backend/internal/handler/admin/account_reasoning_policy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2bb0731af6bfdef233b77aee413e6ff6fec49178dab55aeb3b52821e41cc5473", - "review_fingerprint": "2bb0731af6bfdef233b77aee413e6ff6fec49178dab55aeb3b52821e41cc5473", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "完整静态审阅224行;本轮未执行,不以静态审阅冒充测试通过。", - "evidence": [ - "覆盖省略字段、显式开关、异常输入、导入/更新接线和目标集合验证边界;源码无本轮实现改动,沿最小测试规则复用既有行为而不增加运行。" - ] - }, - { - "path": "backend/internal/handler/admin/account_taxonomy.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "93a3c5e8b08cec959040deda69ee62f3a395a08f877f4b3f2263c4536d49d372", - "review_fingerprint": "93a3c5e8b08cec959040deda69ee62f3a395a08f877f4b3f2263c4536d49d372", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/account_taxonomy_handler_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cb646d25b23cb8a70df66acd6d91d83947b027c1c129766c72512b36cc44a0f8", - "review_fingerprint": "cb646d25b23cb8a70df66acd6d91d83947b027c1c129766c72512b36cc44a0f8", - "review_status": "reviewed", - "decision": "adapter", - "owner": "account-tools", - "reason": "分类适配层测试(新下游文件)。断言:带 X-Sub2API-Plugin 头的 SetAccountTaxonomy 响应只含 account_id,不含 credentials 与 synthetic-secret(防插件 UI 拿到账号凭据);facets DTO 为稳定 snake_case 且 folder/tag 恰好 6 个键(含 cindy_total/cindy_insufficient_count),group_id 透传;filter 目标的批量分类请求把控制台过滤(uncategorized/tags)与 expected_match_count、folder_action/folder_id、tag 增删完整入 payload,且仅投递 1 个任务项(具体目标在 worker 解析)。校验规则的 subject 是 account-tools 插件(fixture 安装),测试静态阅读未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S03-handler-admin-account-1-review.json", - "L71-86 插件响应脱敏断言(NotContains synthetic-secret/credentials,Contains account_id:7)。", - "L169-201 filter 目标批量分类:params.Items 长度 1、payload 过滤字段逐项断言,对应 account_taxonomy.go L357-374 与插件 taxonomy.bulk 校验。", - "Static read only; no test/build execution, no production behavior verified." - ] - }, - { - "path": "backend/internal/handler/admin/account_test_plan.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "4777524f26f774965ef7e868361af226ddbbc461115b4c9a26e79802f6d8e556", - "review_fingerprint": "4777524f26f774965ef7e868361af226ddbbc461115b4c9a26e79802f6d8e556", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/account_test_plan_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d41b057f71c57f017aa1ec40ee1ca03b0890efabdd6c0163b2cee234fac4f096", - "review_fingerprint": "d41b057f71c57f017aa1ec40ee1ca03b0890efabdd6c0163b2cee234fac4f096", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "纠正 legacy 零可选调用的错误假设;ordinary/legacy 对照实际复验。已存 canonical 同源/core matrix 本轮不重跑。 全文结论来自逐路径冻结审查,区域项未导入;实际测试、前代理报告与未运行边界见同一报告。", - "evidence": [ - "artifacts/evidence/v027-astra-single-test-policy-boundary-review.json#source_index:backend/internal/handler/admin/account_test_plan_test.go", - "artifacts/evidence/v027-astra-single-test-policy-boundary-review.json#validation", - "commit 7b4de3ae7; exact SHA rechecked at integration" - ] - }, - { - "path": "backend/internal/handler/admin/account_today_stats_cache.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3c63ab92d3462febf94d422132df43a14432ffd10d4c98bc414de98b32f1a490", - "review_fingerprint": "3c63ab92d3462febf94d422132df43a14432ffd10d4c98bc414de98b32f1a490", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "完整审阅34行及唯一新增下游hunk;失效清空全部batch并隔离更早的在途填充。", - "evidence": [ - "30秒缓存和规范化后账号ID集合key保持;入参为空不做失效,其余失效调用Clear清空全部batch,范围偏宽但不产生跨管理员凭据泄漏。", - "InvalidateAccountTodayStatsCache经唯一UsageCommitObserver生产consumer接入;本轮授权扩展把通知移到确认日志持久化以后。", - "Generation及SetIfGeneration在snapshot_cache实现;GetBatchTodayStats在查询前采样generation,迟到结果可回给原请求但不能重新填入已失效缓存。" - ] - }, - { - "path": "backend/internal/handler/admin/admin_basic_handlers_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6f41f89c03b623ddb6a2eafee2467b8b91f332537eb507a6999387a734a9afb4", - "review_fingerprint": "6f41f89c03b623ddb6a2eafee2467b8b91f332537eb507a6999387a734a9afb4", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "管理端 user/group/proxy/redeem 路由冒烟测试。下游相对 aea725f 仅新增 TestGroupHandlerRejectsLegacyProfitControlWrites(L269-L305):create/update 载荷携带 profit_control_enabled / profit_min_margin / profit_safety_buffer(含显式 null)时断言 400 且响应含“利润控制不再支持”,锁定利润控制业务从核心分组写路径下线后的迁移提示。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L269-L305: three payloads (POST create, PUT update with 0, PUT with explicit null) must get 400 + migration hint; the guard is the json.RawMessage presence check at group_handler.go L661-L664 / L804-L807.", - "L14-L70 setupAdminRouter wires the stubAdminService router; the remaining smoke assertions (L72-L411) are unchanged upstream content.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/admin_service_stub_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f187f9bc124b9e0ed4cfbb1f2acd1f9491dd24eee6b7bb0724d4ac68d5e16ff9", - "review_fingerprint": "f187f9bc124b9e0ed4cfbb1f2acd1f9491dd24eee6b7bb0724d4ac68d5e16ff9", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "admin 包共享的 service.AdminService 桩实现(855 行,分页/过滤模拟与调用捕获)。下游相对上游仅新增 5 个 Cindy 余额/封禁方法的空实现(L568-L586:ClearCindyBalanceInsufficient、Preview/DeleteCindyInsufficient、Preview/DeleteCindyBanned),以满足核心 AdminService 接口新增方法的编译约束;桩本身无业务规则,Cindy 余额业务在 service/repository 层(Codex 负责区域),此处不作其归属判断。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "Diff vs aea725f is exactly the five no-op Cindy methods L568-L586 returning zero-value previews/results; interface assertion at L855 (var _ service.AdminService).", - "Real implementations live in service/admin_cindy_balance.go and repository/account_repo_cindy_balance.go with routes in server/routes/admin.go L468-L501 — outside this slice.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/batch_update_credentials_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "05046ec80e791b4d686f195c7e6a2044bae4cbe8ba44db7917b2832b76b5d8aa", - "review_fingerprint": "05046ec80e791b4d686f195c7e6a2044bae4cbe8ba44db7917b2832b76b5d8aa", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "批量更新账号凭据接口测试。下游把上游的同步 200+成败明细模式改为异步账号任务:合法请求断言 202 Accepted,requireSubmittedAccountJob 捕获 AccountJobKindBatchUpdateCredentials 任务与载荷,executeSubmittedAccountJobItems 执行任务项后逐项断言成功/失败(credentials_update_failed、account_not_found)且非 fail-fast(3 次 UpdateAccount 调用);参数类型校验(intercept_warmup_requests 非 bool、account_uuid 非 string → 400)仍是同步前置。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L45-L133 rewritten to 202 + job submission/execution via helpers from account_job_submit_test.go (attachAccountJobSubmitter, setAccountJobTestIdempotencyKey).", - "L148-L234: 400-type validations stay synchronous; null account_uuid submits a job with nil Value.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/channel_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3c3c37119ecaf5e914de3b727c1e74f18ff5340b3640d84dac02c3f6d316a935", - "review_fingerprint": "3c3c37119ecaf5e914de3b727c1e74f18ff5340b3640d84dac02c3f6d316a935", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "渠道 handler 纯函数测试:channelToResponse 纯透传(BillingModelSource 空值兜底移至 service 层)、pricingRequestToService 在 allowChannelMultipliers=false 时丢弃全部倍率字段防止渠道倍率污染账号成本口径、时段计价映射、模型默认价(claude-fable-5-1 缓存 TTL 定价与 max_reasoning_effort_multiplier=3)。下游新增 TestSyncPricingModels_CindyUsesManagedCatalog(L569-L578)断言 platform=cindy 在 LiteLLM 同步接口返回 400:cindy 模型目录由插件托管目录提供,platformToLiteLLMProvider(channel_handler.go L637-L648)确无 cindy 项。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L569-L578 new: GET /channels/pricing/sync-models?platform=cindy -> 400 (UNSUPPORTED_PLATFORM path in SyncPricingModels L652-L669).", - "L454-L489 multiplier gating test and L588-L628 fable-5-1 cache pricing assertions read in full; unchanged vs upstream except the cindy test.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/cindy_balance_probe_handler.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "34f9012e932c671394f26e65378940893848301f2e8c7694e2994afd1eab5579", - "review_fingerprint": "34f9012e932c671394f26e65378940893848301f2e8c7694e2994afd1eab5579", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/cindy_balance_probe_handler_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "934e74ca56ab3c39eebcc94153198be0a9d5009b0dd75fa48d00dd85f34dc774", - "review_fingerprint": "934e74ca56ab3c39eebcc94153198be0a9d5009b0dd75fa48d00dd85f34dc774", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/grok_import_probe.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "608caba5bb2cdd058f510cb64101ca2df9b0ceaea2232b6f8d3bbc63fade16bf", - "review_fingerprint": "608caba5bb2cdd058f510cb64101ca2df9b0ceaea2232b6f8d3bbc63fade16bf", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "Grok OAuth 账号导入后的主动配额探测调度器:包级单例、并发 3、队列上限 64(超限丢弃并 Debug 日志)、pending/inFlight 去重、25s 超时、panic 恢复,日志仅含错误码/reason 不含凭据。下游相对上游仅在 ProvideAccountHandler 注入参数新增 cindyJobMutations service.AccountJobCindyMutationRunner 并赋给 handler.cindyJobMutations(L214、L233),属宿主依赖装配,不含 Cindy 业务逻辑。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "Scheduler lifecycle L60-L127: dedupe maps, queue cap grokImportProbeQueueLimit=64, worker count bounded by concurrency, finish() clears inFlight.", - "Diff vs aea725f: only the two cindyJobMutations lines; runner interface defined at service/account_job.go L180 (one ordinary PostgreSQL mutation runner), wired in cmd/server/wire_gen.go L209.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/group_cindy_split.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "22c453778bb8d737c5774f62095b85933630f05cf41be984b43b3d38f5a6dee0", - "review_fingerprint": "22c453778bb8d737c5774f62095b85933630f05cf41be984b43b3d38f5a6dee0", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/group_cindy_split_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "26ec56de824ff11bb9581e83c9be054bd73b7789ef74d7d8fe159c4bf401e4ea", - "review_fingerprint": "26ec56de824ff11bb9581e83c9be054bd73b7789ef74d7d8fe159c4bf401e4ea", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/group_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "79d8490d202460df6c35e2a49e47a996501048b3679d3da82cc18eab42a81a99", - "review_fingerprint": "79d8490d202460df6c35e2a49e47a996501048b3679d3da82cc18eab42a81a99", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "管理端分组 CRUD/复合路由/倍率/RPM 覆盖 handler(1149 行)。下游相对上游:platform 枚举加入 cindy;Profit* 三字段改为 json.RawMessage,Create/Update 只要字段出现(含 null)即 400“利润控制不再支持”且不再向 service 传递(利润控制业务下线);GetGroupModelAllowlistCandidates 增加 groupID==0 且 platform==cindy(区分大小写)的本地创建目录豁免,其余请求仍受简洁模式高级操作限制。分组管理是宿主通用能力,Cindy 目录内容由 adminService.GetGroupModelsListCandidates 提供,handler 不持有目录数据。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L209-L211/L284-L286 RawMessage fields; L661-L664 (Create) and L804-L807 (Update) reject any presence with 400; CreateGroupInput/UpdateGroupInput no longer carry Profit fields.", - "L610-L635 localCindyCreateCatalog carve-out (exact-match service.PlatformCindy, groupID==0 only); simple-mode sanitizers L166-L181; optionalLimitField null/-1 semantics L44-L91.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/group_handler_platform_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "93572923d878ff955f5c78d87738013c12fedbc729933680c503f078f460be12", - "review_fingerprint": "93572923d878ff955f5c78d87738013c12fedbc729933680c503f078f460be12", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "分组平台枚举 binding 回归:允许清单加入 cindy(create/update 双向断言),非法值(moonshot、大小写 Kimi、尾随空格、glm、bogus)仍被拒;复合路由 target_platform 允许 CN 平台并拒绝 composite。下游 diff 即允许清单加 cindy 与注释精简。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L25-L46 allowed list now includes cindy for both CreateGroupRequest and UpdateGroupRequest binding.", - "L48-L84 invalid platforms and composite-route target assertions unchanged upstream content.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/group_handler_simple_mode_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "37b2bee30944b8028eabb1281871ebc0c9f6b8608bc24c7bd08d238fc7c2972e", - "review_fingerprint": "37b2bee30944b8028eabb1281871ebc0c9f6b8608bc24c7bd08d238fc7c2972e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "简洁模式分组接口测试:创建/更新载荷商业字段消毒、composite 平台前置拒绝、删除走 DeleteGroupIfEmpty(非空 409)、响应字段白名单(rate_multiplier/model_pricing 等不得外漏)、高级操作一律 403 且不触达 service。下游新增 TestGroupHandlerSimpleModeAllowsOnlyLocalCindyCreateCatalog(L285-L314):仅 /groups/0/model-allowlist-candidates?platform=cindy 放行并把 (0, cindy) 透传给 GetGroupModelsListCandidates,其余(真实分组 id、openai、大小写 Cindy、缺参、-1、非数字 id)403/400 且 candidateCalls 为零,证明被挡请求不会查询分组/账号池。newSimpleModeGroupRouter 改收 service.AdminService 接口以便注入捕获桩。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L285-L314 seven-case table incl. negative/invalid id -> 400 before the gate; blocked cases assert zero service calls.", - "L47-L97 sanitizer assertions and L316-L355 advanced-operation 403 matrix are upstream content plus the interface-typed router param (L17).", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/group_plugin_options.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "b5aacd4249941ff4c4838cfcebaf221ab577e4a65a284027aaea77ba3b205c0c", - "review_fingerprint": "b5aacd4249941ff4c4838cfcebaf221ab577e4a65a284027aaea77ba3b205c0c", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "完整审阅32行;prompt-audit选择器只适配既有管理员分组可绑定性判断。", - "evidence": [ - "仅返回id/name/platform/status,不包含credentials或原始settings;simple模式与逐组bindability过滤保留。", - "追踪registerPromptAuditRoutes:管理员认证、插件全局scope及UI capability在handler之前执行;此处没有第二个插件配置写入口。", - "没有为本静态只读审阅额外运行服务/浏览器测试。" - ] - }, - { - "path": "backend/internal/handler/admin/openai_oauth_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "677bbd4803ca036825b82d5db018877ed1f7ac887c6a0a84851d5857a58c7f5d", - "review_fingerprint": "677bbd4803ca036825b82d5db018877ed1f7ac887c6a0a84851d5857a58c7f5d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "OpenAI OAuth 管理 handler:授权链接/换码/刷新令牌、按账号刷新(spark 影子账号在打上游前早拒)、Codex PAT 建号(sanitize credential extras、指纹入 extra)、配额查询/刷新/重置(重置后处理用 context.WithoutCancel+8s 超时,防止浏览器中断导致重复消耗不可退还的重置积分)、影子账号创建。下游相对上游仅在 CreateAccountFromCodexPAT 增加 service.ValidateOpenAIReasoningPolicyExtra(req.Extra)(L373-L376):校验 extra 两个推理策略键为布尔,规则在 service/admin_account.go L401-L410,handler 只做委派。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "Diff vs aea725f is the 4-line validator call; interface-nil guards documented at L90-L98 avoid non-nil interface holding nil pointer.", - "RefreshQuota L506-L539 treats snapshot persist failure as partial success (cache_persisted=false) instead of discarding the fetched usage.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/payment_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a8a4e704b14ef517954b1455f18504cdc2d225e1a5233751471c4fddadcc0b73", - "review_fingerprint": "a8a4e704b14ef517954b1455f18504cdc2d225e1a5233751471c4fddadcc0b73", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "支付订单响应消毒与订阅套餐投影测试:sanitizeAdminPaymentOrderForResponse 从 provider_snapshot 提取 currency 且序列化结果不含 provider_snapshot;adminSubscriptionPlansForResponse 保留 composite 分组信息、currency 与时间戳(防止编辑保存把套餐货币静默清空)。下游 diff 仅在 t.Fatal 后补 return(控制流安抚,不改断言语义)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L34-L49 sanitizer assertions; L100-L107 currency/timestamps preservation rationale in comments.", - "Diff vs aea725f: single `return` after t.Fatal at L37.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/plugin_account_views.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "72fbce6527a9b678bedb5e6d19fe7a046cbfc9a0722f37cb5e4b387fdec73c43", - "review_fingerprint": "72fbce6527a9b678bedb5e6d19fe7a046cbfc9a0722f37cb5e4b387fdec73c43", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文复核请求局部view入口:有界base64url身份与JSON体捕获、header/body相等、actor绑定UI session;无view的原生数组/异构items不误作插件载荷。重复merge从同actor成功review的加密payload取原集合/摘要;retained仅host注册读取/取消,generic actions/jobs拒绝view origin。列表/导出有限query及全部显式目标由真实账号重验,主action owner与view owner独立,不全局改Axios/核心权限。实际no-op/非法上下文/generic RPC/类型化query方法已绿,HTTP全端到端不在本证据中。", - "evidence": [ - "artifacts/evidence/v027-account-view-integration-review.json#verification", - "Current complete source read plus exact frozen/current SHA verification; no full-application runtime claim." - ] - }, - { - "path": "backend/internal/handler/admin/plugin_account_views_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "02dbaf3ea767dd50846ebd7449c1cabe66de20f677110bee89275307dc7da7a6", - "review_fingerprint": "02dbaf3ea767dd50846ebd7449c1cabe66de20f677110bee89275307dc7da7a6", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/plugin_contract_fixture_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ac399eb6e7e6be598dd522e5b71dad4b2866714d87dc69953f43b5347ad72049", - "review_fingerprint": "ac399eb6e7e6be598dd522e5b71dad4b2866714d87dc69953f43b5347ad72049", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "5 行测试装置(新增文件):init 调用 testextensions.Install(),即 service.ConfigureProcessExtensionServices(catalog.New(), operations{}),使 admin 包测试在进程内扩展契约桩上运行而非真实插件进程。宿主↔插件桥接的测试胶水,无业务规则。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "testextensions.Install at internal/testextensions/fixtures.go L74 configures the in-process extension catalog/operations pair.", - "New downstream file (git ls-tree aea725f prints nothing for this path).", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/plugin_error_diagnostics.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "0dd69d57108ea56e0d225745fbee4a21629d0e3f25e5d8307b40570524cbc93f", - "review_fingerprint": "0dd69d57108ea56e0d225745fbee4a21629d0e3f25e5d8307b40570524cbc93f", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "The named administrator resource parses a positive record ID, delegates existing monitoring authorization and log retrieval, then returns only the manager's authorized projection.", - "evidence": [ - "route package compilation and projection scope test; registered behind existing admin middleware and resource binding" - ] - }, - { - "path": "backend/internal/handler/admin/plugin_handler.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "49eb27208f8fde7f4d6dc1c1aba37e06e5bab1182eb9231aa9005c31167728c5", - "review_fingerprint": "49eb27208f8fde7f4d6dc1c1aba37e06e5bab1182eb9231aa9005c31167728c5", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/plugin_precondition.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "529071ee923bd937c016ca877b49c0af7ce00d8f06e69db46a34b9f429eeb1e1", - "review_fingerprint": "529071ee923bd937c016ca877b49c0af7ce00d8f06e69db46a34b9f429eeb1e1", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New parser validates positive canonical int64 revision and one lowercase SHA256 header value, rejects missing required headers, adds only host/private service context, maps state/session conflicts to typed 409, and emits raw config plus same-snapshot response headers.", - "evidence": [ - "artifacts/evidence/v027-astra-plugin-precondition-review.json: read/write receipt protocol, HTTP/Frame/API targeted outcomes and shared-file boundaries" - ] - }, - { - "path": "backend/internal/handler/admin/plugin_precondition_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "12f065e61f7b75dab1ddc47a152ecf89968c1a4e16df766845569fa1af652816", - "review_fingerprint": "12f065e61f7b75dab1ddc47a152ecf89968c1a4e16df766845569fa1af652816", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New direct HTTP cases prove all seven write/action entry points reject absent conditions before work; invalid revisions/digest reject; five lifecycle endpoints reject stale revision or package; GetConfig performs one read and returns raw code-bearing JSON with version/no-store headers. Tests do not invoke a plugin/model.", - "evidence": [ - "artifacts/evidence/v027-astra-plugin-precondition-review.json: read/write receipt protocol, HTTP/Frame/API targeted outcomes and shared-file boundaries" - ] - }, - { - "path": "backend/internal/handler/admin/plugin_resource_scope_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b90e175ad4ebceb9d1a696f2e37d3c753a4db79e39089ec3a93b99eb538a6205", - "review_fingerprint": "b90e175ad4ebceb9d1a696f2e37d3c753a4db79e39089ec3a93b99eb538a6205", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "本地 Gin 夹具锁定嵌套 selected 的显式 ID 优先级,空选择无法转为全选。", - "evidence": [ - "backend/internal/handler/admin/plugin_resources.go", - ".downstream/implementation-v0.2.7.md#可复用验证" - ] - }, - { - "path": "backend/internal/handler/admin/plugin_resources.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "5efc93a61fa389911accd3ca1b9fd6803575bbe7eb2fe8eaf50e220d59dd8e62", - "review_fingerprint": "5efc93a61fa389911accd3ca1b9fd6803575bbe7eb2fe8eaf50e220d59dd8e62", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/plugin_update.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "c798b657b2184c79c1cf621210d1f2bd617fae1c91a2126e76e5f70fbd15c1ab", - "review_fingerprint": "c798b657b2184c79c1cf621210d1f2bd617fae1c91a2126e76e5f70fbd15c1ab", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/plugin_upload_guard_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "559bc78bcfad812769a455a2fba3d5f05def2acff58cef23d776920fd817161f", - "review_fingerprint": "559bc78bcfad812769a455a2fba3d5f05def2acff58cef23d776920fd817161f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New multipart upload test uses a valid but non-runnable archive and existing disabled identity, then verifies HTTP/body 409, PLUGIN_ALREADY_INSTALLED reason and explicit dedicated-update guidance. The single test actually ran and passed without starting the archive program.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Actual targeted execution is recorded in verification below." - ] - }, - { - "path": "backend/internal/handler/admin/provider_identity_validation_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5c092b2c684298980b1296aa53f4c89cce9dd4f563e80bbd993dd4edbcfee547", - "review_fingerprint": "5c092b2c684298980b1296aa53f4c89cce9dd4f563e80bbd993dd4edbcfee547", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "新增测试:validateCreateAccountProviderIdentity(account_handler.go L217-L229)以 service.ResolveAccountProviderIdentity 解析的最终轴为准——cindy 平台 + laxarouter api_key 凭据推导 wire_platform=openai、provider_profile=cindy_laxa_v1;请求显式给出不一致的 wire_platform 或 provider_profile 时返回 mismatch 错误。锁定账号创建时提供方身份三轴一致性(宿主准入校验)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L10-L26: positive case then two mismatch cases (gemini wire, cindy_future_v2 profile) with ErrorContains assertions.", - "Constants WirePlatformOpenAI / ProviderProfileCindyLaxaV1 defined in service/provider_identity.go L11-L12.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/scheduled_test_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d02157941fee4fc47306c357c803b21f74d16113b3f0ee8f2cf6913bfc3eb8e6", - "review_fingerprint": "d02157941fee4fc47306c357c803b21f74d16113b3f0ee8f2cf6913bfc3eb8e6", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/admin/setting_codex_ticket_proxy.go", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "38bd6f3c640c0de800a3f8e3830bc8a22b937f95caf35fc5eef26c5717449582", - "review_fingerprint": "38bd6f3c640c0de800a3f8e3830bc8a22b937f95caf35fc5eef26c5717449582", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "管理端设置页“采集代理连通性预检”的 HTTP 适配:POST /admin/settings/openai-codex-ticket/proxy-test 读取 proxy_url,置 Cache-Control: no-store,转交 OpenAIGatewayService.TestCodexTicketProxy(codex_ticket_plugin.go L115-L138 → InvokeAdminExtension(installation, 0, \"proxy.test\"),由 codexrip.codex-runtime 插件执行 TCP/TLS/HTTP 探测),失败只回固定文案“无法完成代理测试”。上游无此文件,整文件为下游新增;宿主不做探测、不保存代理,判为 codex-runtime 适配。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S62-codex-ticket-T1-review.json", - "L9-L11 SetCodexTicketGateway 由 handler/wire.go L61 注入;L13-L32 TestCodexTicketProxy:ShouldBindJSON 失败 400、gateway 为 nil 503、err 时 500 且不透出 err 文本;路由 routes/admin.go L692 adminSettings 分组。", - "响应泄露检查:返回体为 CodexTicketProxyTestResult{failure_detail,success,network_reachable,protocol,http_status,code,message,stages[name,success,duration_ms,message],certificate_trust,certificate_fingerprint,protocol_suggestion}(codex_ticket_proxy.go L21-L33),无代理 URL 字段;宿主在 codex_ticket_plugin.go L132-L136 用固定中文文案覆写 message;插件侧 stages 的 message 仅为 \"HTTP %d\"(plugins/codex-runtime/internal/tickets/proxy.go L177/L209)。请求侧 proxy_url 不写日志。", - "不宣称:未验证插件探测逻辑本身(S48 范围);未执行接口或网络测试。" - ] - }, - { - "path": "backend/internal/handler/admin/setting_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5d89d056c18e7c4b4d1ca651772a939dc2b913ff6750f5604f20f32291f265eb", - "review_fingerprint": "5d89d056c18e7c4b4d1ca651772a939dc2b913ff6750f5604f20f32291f265eb", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "系统设置读取 handler(GET /admin/settings 组装 dto.SystemSettings,558 行)。下游相对上游:新增 Cache-Control no-store;payload 增补 OpenAI 拒答恢复五字段(keywords 复制切片防共享)与 CindyManagedCompatibility 块——其中 Enabled/VerifiedTextModels/CompatibilityAliases 经 service 桥接查询 cindy 插件目录(cindy_capability_catalog.go queryCindyCatalog、cindy_feature_flags.go),路径与 prompt_cache_key 描述是 api_contract_test.go L959-L967/L1296-L1304 与前端 settings.ts 类型共同钉死的静态展示契约;新增 codexTicketGateway 字段(本文件 GET 载荷不含任何 openai_codex_ticket 键;写路径 setting_handler_update.go L498-L500 对三个该前缀键返回 409 迁移提示,满足“设置写路径不得写插件业务开关”的检查项)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L104-L110 no-store + L271-L276 refusal-recovery fields; L424-L438 cindyManagedCompatibilitySettings mixes plugin-bridged values with contract-pinned literals.", - "Codex ticket keys absent from the L137-L405 payload struct; the 409 write guard and setting_handler_codex_ticket_test.go assert the plugin-only write path (cross-referenced, other slice).", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/setting_handler_audit.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ecb64e8f051a0a588791261ca738717db2267b7151cc631d1a8138eee7848eb6", - "review_fingerprint": "ecb64e8f051a0a588791261ca738717db2267b7151cc631d1a8138eee7848eb6", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "完整审阅对官方baseline的2个下游hunk(import与7类新增字段比较);未把891行未变官方审计正文声称为逐行新审阅。", - "evidence": [ - "新增refusal recovery、cyber failover、两个只读兼容字段及rewrite启用/关键词/替换文本的changed-field判定。", - "切片比较使用slices.Equal;审计输出仍仅user_id/role/变更字段名,不打印配置值、关键词内容、密码或proxy secret。", - "未修改其余官方diff helpers;本文件仅静态审阅,未执行单独测试。" - ] - }, - { - "path": "backend/internal/handler/admin/setting_handler_codex_ticket_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5c745a48a82435d3731b85d09361c7871bb71b4ed4d93e95e51162200d2be5d9", - "review_fingerprint": "5c745a48a82435d3731b85d09361c7871bb71b4ed4d93e95e51162200d2be5d9", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "完整静态审阅41行;本轮未执行。", - "evidence": [ - "测试断言三类旧ticket写字段被409拒绝、GET/其他设置更新不泄露proxy secret且保留原seed;与本次全部下游设置差异一致。" - ] - }, - { - "path": "backend/internal/handler/admin/setting_handler_partial_payload_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "dae4ef9ecbfa43bc5612db55b3173f44ba95779345f59079c1ac783fa8ebb6b1", - "review_fingerprint": "dae4ef9ecbfa43bc5612db55b3173f44ba95779345f59079c1ac783fa8ebb6b1", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "设置保存的部分载荷语义测试:未发送键保持存量、显式空值清除、smtp_from_email 别名可写、Turnstile/腾讯天御双开互斥、四凭据齐备校验、站点区域保持与未知值归一回 CN、subscription_enabled 显式 false 可写且省略不回翻。下游新增:存量补 Turnstile site/secret key;TestUpdateSettingsIgnoresDeprecatedAPIKeyCompatibilityWrites 断言两个已废弃 openai_apikey_* 兼容开关的写入被忽略(存量保持);TestUpdateSettingsValidatesTurnstileSiteKeyWhenEnabledFlagIsOmitted 断言启用态下清空 site key 被 400 拒绝且存量不变。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L44-L57 deprecated api-key compat switches stay read-only; keys still parsed for runtime at service/setting_gateway_runtime.go L236-L267.", - "L207-L221 turnstile site-key validation with omitted enabled flag; L20-L42 partial payload baseline extended with stored turnstile keys.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/setting_handler_refusal_recovery_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "62213c16d64af67fecac3480bfdfe10fb0e703c2b042d9ba0414126aba0aad3c", - "review_fingerprint": "62213c16d64af67fecac3480bfdfe10fb0e703c2b042d9ba0414126aba0aad3c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "新增测试:OpenAI 拒答恢复设置的持久化归一(关键词修剪去重小写化为 [sorry, 我不能])、rewrite 开启但 replacement 为空 400、cyber failover 与 CyberSessionBlock 互斥(含 recovery 关闭时的独立冲突路径)、diffSettings 审计只报字段名不含替换文本内容。拒答恢复引擎实现于核心 service(openai_refusal_recovery*.go 及 WS/HTTP 转发链),设置面归核心。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L14-L32 normalization assertions on repo.values; L46-L71 two conflict rejections; L73-L93 diffSettings names-only audit.", - "Engine and defaults live in service/openai_refusal_recovery.go (default keyword list L35); plugins/codex-runtime only lists a 'refusal' chat field name, no duplicate engine.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/setting_handler_update.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "002dda295bdff89870e295d99c826302142943b77edd70a5ca285112705ae5b9", - "review_fingerprint": "002dda295bdff89870e295d99c826302142943b77edd70a5ca285112705ae5b9", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "完整审阅对官方baseline的全部8个下游hunk,并追踪其验证/持久化/读回调用链;2540行中未变官方业务正文复用baseline,不声称整段重测。", - "evidence": [ - "新增可选refusal/cyber/rewrite请求字段保留部分更新语义;响应no-store;旧openai_codex_ticket_enabled/harvest_proxy_url/clear_proxy字段一经提交即409,发生在任何写入之前。", - "Turnstile site省略时恢复原值,并用合并后的effective enabled状态校验;原有step-up启停安全前置条件不改变。", - "refusal字段省略则保留原值,关键词切片复制;旧alpha-search/prompt-cache兼容字段仅从既有值读取。NormalizeOpenAIRefusalKeywords及ValidateOpenAIRefusalRecoverySettings仍在写入前执行。", - "沿UpdateSettingsWithAuthSourceDefaultsOmitting核对SetMultiple与省略字段保留;审计移至持久化后读回结果,记录实际归一化字段。", - "response中的CindyManagedCompatibility从插件运行配置派生;旧ticket seed只读兼容,不形成另一个ticket配置写入口。", - "setting_handler_codex_ticket_test.go完整静态审阅:legacy写入409、未反射proxy secret、无关site_name可保存且seed保留、GET no-store且无旧ticket字段。本轮未执行该既有测试。" - ] - }, - { - "path": "backend/internal/handler/admin/snapshot_cache.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "188cf6b44e42f47a37db713f72ee9bbbf5dab61bc1b9335482d84d199e98bb52", - "review_fingerprint": "188cf6b44e42f47a37db713f72ee9bbbf5dab61bc1b9335482d84d199e98bb52", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整审阅183行,覆盖全部5个下游hunk;修复Clear被在途loader撤销及新请求合并到旧singleflight的问题。", - "evidence": [ - "Clear在同一mutex内递增generation并更换entries。SetIfGeneration仍生成正常响应entry,但仅当generation匹配时发布缓存。", - "GetOrLoad的singleflight key包含generation;Clear之后的新请求不再加入旧generation任务。旧任务完成不会覆盖新一代缓存。", - "既有Set签名、TTL、JSON payload及ETag规则保持兼容;直接影响的miss/hit和并发singleflight两个既有测试与三个新增失效测试已在同一最小green命令运行。" - ] - }, - { - "path": "backend/internal/handler/admin/snapshot_cache_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4bb389cd291dd10c8da974b10b4f20a283957a9d0846f3823feeec80ef1283c7", - "review_fingerprint": "4bb389cd291dd10c8da974b10b4f20a283957a9d0846f3823feeec80ef1283c7", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "完整审阅257行;新加3个确定性失效测试,加上2个直接影响既有测试,仅执行一次green最小集合。", - "evidence": [ - "ClearDoesNotRepublishInflightResult用channel暂停旧loader,Clear后写入新值再释放旧loader,确保新值未被覆盖。", - "ClearSeparatesNewSingleflight确保Clear后新loader能独立开始;超时仅为1秒失败边界,非sleep驱动竞态。", - "AccountTodayStatsInvalidationFencesSampledGeneration验证手动batch查询generation在失效后不可存储,而新generation可存储。", - "GetOrLoad_MissThenHit及GetOrLoad_ConcurrentSingleflight为直接影响的既有API兼容测试;其余测试只读不重跑。" - ] - }, - { - "path": "backend/internal/handler/admin/system_prompt_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "124d31c83f4a895ad105fe389677fb540ce41a3234e8ad281e7d2f97bc416521", - "review_fingerprint": "124d31c83f4a895ad105fe389677fb540ce41a3234e8ad281e7d2f97bc416521", - "review_status": "reviewed", - "decision": "adapter", - "owner": "prompt-skills", - "reason": "业务 System Prompt 目录与远程技能注册表的管理 HTTP 适配层(934 行新增文件):模板 CRUD/版本/发布/回滚/运行时开关/预览,skill-registry 版本/同步/发布。修订并发、种子保护、组合模式、bundle 校验等业务规则全部委派 BusinessSystemPromptService 与 RemoteSkillRegistryService;本文件只做 actorID 鉴权、参数与 multipart 解析(MaxBytesReader 上限、恰一次 expected_revision、prompt_capture ≤上限且 UTF-8、RemoveAll 清理)、稳定错误码映射(writeBusinessSystemPromptError 六类)与审计 extras(只记录哈希/长度/修订,不记录提示词正文)。归 prompt-skills 域的宿主适配;发布接口的 expected_revision 允许缺省为 0,冲突校验由 service 端修订检查兜底(本文件不实现)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "parseRemoteSkillSyncMultipart L323-L369: bounded read, exactly-one revision field, UTF-8 and size validation, deferred RemoveAll.", - "Error mapping L207-L236 to stable reasons (system_prompt_revision_conflict etc.); audit extras L313-L319/L670-L676 carry sha256/byte_length only; routes mounted in server/routes/admin.go L180-L206.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/system_prompt_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "94d12dce55084a228ba53b925e67f3235d71c2de3bddca3ed5903ed8d6a57974", - "review_fingerprint": "94d12dce55084a228ba53b925e67f3235d71c2de3bddca3ed5903ed8d6a57974", - "review_status": "reviewed", - "decision": "adapter", - "owner": "prompt-skills", - "reason": "上述适配层的合同测试(新增):StartSkillSync 接受 multipart prompt_capture 并把 actorID/expectedRevision/promptProvided 传入 store(202 Accepted);版本详情返回 raw/effective body 而注册表摘要不泄露正文(runtime.active_prompt.raw_body 不存在);writeBusinessSystemPromptError 六类错误的稳定 reason 与状态码;运行时响应字段映射(SHA 小写化、Degraded 透传);selectVersion 取最新或指定版本、未知 ID 报 not found。桥接测试,静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L20-L51 multipart contract; L53-L84 body leak boundary between version detail and registry summary (gjson assertions).", - "L148-L190 stable protocol codes table; L192-L219 runtime mapping and selectVersion behavior.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/admin/user_platform_quota_admin_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4e00849d52d6ee195ac48bc81a70f958cdf1584af99ccc309b2cfc3bb9bb956e", - "review_fingerprint": "4e00849d52d6ee195ac48bc81a70f958cdf1584af99ccc309b2cfc3bb9bb956e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "用户平台配额管理测试:三档全空平台不 upsert(由 UpsertForUser 软删分支处理)、全部为空等价清空、0 为显式禁用仍落库、重复/非法平台/负限额/超量条目 400、成功后按 AllowedQuotaPlatforms 全量失效计费缓存、窗口重置成功/非法窗口/非法平台/未配置 404/用户不存在 404。下游 diff:请求样例加入 cindy 平台并更新注释(缓存失效平台含 opencode_go)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L94-L130 success case now sends six platforms incl. cindy; upserted records still only the two configured ones.", - "L127-L129 cache invalidation count tied to service.AllowedQuotaPlatforms (so admitting cindy/opencode_go is service-driven, not test-local).", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/cindy_balance_handler_failover_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ea18b88d465698d02a2e5e94936a29a8c1d4fa4fbbe5a25fabc994a2b01c590c", - "review_fingerprint": "ea18b88d465698d02a2e5e94936a29a8c1d4fa4fbbe5a25fabc994a2b01c590c", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/cindy_balance_terminal_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "29ea3bb639fbce36d4fce19eadcc311b6f111a467443eff4ffc813b6fe63bc2a", - "review_fingerprint": "29ea3bb639fbce36d4fce19eadcc311b6f111a467443eff4ffc813b6fe63bc2a", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/cindy_catalog_rollback_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fb0c63d193433f1b6a245cd9a3d0f00fafa2abe68c4a6e51853a875f77ea4e74", - "review_fingerprint": "fb0c63d193433f1b6a245cd9a3d0f00fafa2abe68c4a6e51853a875f77ea4e74", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "子进程隔离的“能力目录回滚”测试:父测试用 os.Args[0] 重新拉起自身,先剔除 GATEWAY_CINDY_CAPABILITY_CATALOG_ENABLED 再显式置 false,只运行 Helper(否则被 TestMain 打开的目录污染)。Helper 断言目录关闭时宿主退回旧路由:strictCindyModelAllowed 对 responses/chat 两端点直接放行、ClassifyStrictCindyGroup 为 false、allowOpenAICompatibleMessagesDispatch 回到组开关、openAIMessagesForwardModelForAccount 取 legacy 映射、GetMappedModel 不识别兼容别名、/v1/models 仅回 legacy-model、/v1/models/capabilities 返回 404 且不设上游端点、旧 Laxa 行仍保留 gpt-5.4-mini→openai/gpt-5.6-luna 别名而普通 OpenAI 行与带陈旧 strict 标记的非 OpenAI 组不映射、付费 gpt-5.6-sol 仍被免费池拒绝、WebSocket 混合组/非 OpenAI 组不接收别名。被测对象是宿主 handler 在 cindy-provider 插件配置 CatalogEnabled 关闭时的降级胶水,目录与别名规则本体在 plugins/cindy-provider/catalog,故判为 adapter;下游相对上游为全新文件。静态阅读,未执行。", - "evidence": [ - "Full-file static review (L1-L297, EOF): artifacts/evidence/v027-claude-S52-cindy-rest-T2-review.json", - "Anchors: L21-L30 subprocess re-exec with -test.run=^TestCindyCatalogRollbackHandlerHelper$ and env filtered by withoutCindyCatalogHandlerEnv (L283-L297); L36-L38 fail-fast if service.CindyCapabilityCatalogFeatureEnabled() is true; L53-L84 strict-endpoint bypass, ClassifyStrictCindyGroup=false, legacy Messages dispatch, GetMappedModel alias non-recognition; L97-L120 /v1/models returns only legacy-model and EndpointModelCapabilities -> 404 'Model capability catalog is not enabled'; L126-L175 Responses Luna-alias table (configured_stable_luna, legacy_mixed_group_maps, ordinary_openai_does_not_map, stale-marker Gemini group); L177-L202 paid sol rejected 'not available to the free-key pool'; L204-L264 ChatCompletions forwarded to /v1/responses with same alias policy; L266-L280 WS mixed/non-OpenAI cases keep gpt-5.4-mini.", - "Call chain: handler/openai_gateway_handler.go:275 openAIMessagesForwardModelForAccount, :367 allowOpenAICompatibleMessagesDispatch, :399 strictCindyModelAllowed -> service/cindy_group.go:246 OpenAIGatewayService.ClassifyStrictCindyGroup; gate service/cindy_feature_flags.go:63 CindyCapabilityCatalogFeatureEnabled reads currentCindyProviderConfig (service/plugin_cindy.go:12), env default false at cindy_feature_flags.go:32. Alias inventory the test expects (gpt-5.4-mini -> openai/gpt-5.6-luna) is owned by plugins/cindy-provider/catalog (channel_test.go:12, metadata.go:21); shared fixtures come from cindy_balance_handler_failover_test.go:252/346 and openai_gateway_handler_test.go:3709.", - "Not claimed: the subprocess run, gin handlers and WebSocket helper were not executed; no production behavior edit." - ] - }, - { - "path": "backend/internal/handler/cindy_rollout_testmain_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d6636daf57d7b067873f3f5b519f71c4bd260bdb3bb02f4579c012cbc85cfeb0", - "review_fingerprint": "d6636daf57d7b067873f3f5b519f71c4bd260bdb3bb02f4579c012cbc85cfeb0", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "handler 包的 TestMain 测试基座,不含任何断言:若六个 Cindy/image 特性环境变量都未显式配置且没有 *CINDY*HELPER* 子进程标记,就用 os.Args 重新拉起自身并注入 BalanceDetection/CapabilityCatalog/Search/ImageStudio/ResponsesImageBridge=true 及 SUB2API_CINDY_FEATURE_ON_HANDLER_TEST_MAIN=1,使常规 handler 测试统一在“特性开启”下运行,退出码透传;显式回滚/默认子进程环境不被改写。之所以必须重启进程,是因为 service.cindyRolloutFeatures 在包初始化时一次性快照环境,测试通过 testextensions 夹具把 LegacyCindyProviderConfig() 喂给真实 cindy 插件模块。它是 cindy-provider 特性开关的测试脚手架而非业务或修复证明,判为 reference;下游相对上游为全新文件。静态阅读,未执行。", - "evidence": [ - "Full-file static review (L1-L73, EOF): artifacts/evidence/v027-claude-S52-cindy-rest-T2-review.json", - "Anchors: L17-L22 TestMain re-exec-or-run; L24-L41 shouldReexecHandlerTestsWithCindyFeatures skips when marker env =1, when any of the six feature env names is already configured, or when cindyHandlerTestHelperActive (L43-L52, heuristic: env name contains CINDY and HELPER with non-empty value); L54-L73 reexecHandlerTestsWithCindyFeatures forwards os.Args[1:], appends five *=true envs plus the marker, pipes stdout/stderr, propagates ProcessState exit code.", - "Call chain: service/cindy_feature_flags.go:24-36 cindyRolloutFeatures snapshots env once at init (catalog/search/responsesImage default false, balance default true); LegacyCindyProviderConfig (:75) is consumed by backend/internal/testextensions/fixtures.go:60 which seeds plugins/cindy-provider/catalog module for every cindy.* invocation; handler/plugin_contract_fixture_test.go:10 init() installs that fixture, so CindyCapabilityCatalogFeatureEnabled (service/plugin_cindy.go:12 -> plugin_operation.go:29 invokeProcessExtensionCached) reflects the re-exec env. Helper subprocess tests (cindy_catalog_rollback_test.go L19, openai_alpha_search_cindy_gate_test.go L20) rely on the CINDY+HELPER naming heuristic to avoid a second re-exec.", - "Not claimed: no test binary was run; behaviour of the re-exec under `go test -run` filters was not exercised." - ] - }, - { - "path": "backend/internal/handler/continuation_repair_live_support_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5c30a0eb87d53523672d42a79b280275647393a350ee37122827f2d5984a1d88", - "review_fingerprint": "5c30a0eb87d53523672d42a79b280275647393a350ee37122827f2d5984a1d88", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "continuation_repair_live 构建标签下的密封诊断夹具(新增,普通构建与 CI 不编译):用冻结的生产快照在本进程装配真实 OpenAIGatewayHandler/gateway/Ops/计费栈;所有持久化依赖为内存桩并写死账号 16050/分组 35/用户 920000016050 的归属校验(usage/billing scope mismatch 即报错);设置存储只读、账号快照 JSON 深拷贝防转发链污染、business prompt 启用态直接拒绝装配。诊断夹具不证明生产修复;静态阅读描述结构,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "Fixture guards L36-L108: source policy checks, fast-policy snapshot consistency, read-only setting store (Set/SetMultiple/Delete return diagnostic_read_only).", - "Attribution-locked stores: usage L276-L289 and billing L249-L268 reject any row outside the frozen identity; health counter increments on every account-state mutation L372-L430.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/continuation_repair_live_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "807874cf76b507911d4946dd1d5ecbc471f091c4b99a1676295ac04b3daab3dc", - "review_fingerprint": "807874cf76b507911d4946dd1d5ecbc471f091c4b99a1676295ac04b3daab3dc", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "同一构建标签下的密封实跑主体(1493 行新增):TestContinuationRepairLive 需环境闸门、精确 test.run 选择、/proc/self/fd 密封 CONFIG_FILE、stdout 重定向;每次上游 POST 前需 broker 逐槽授权(4 请求/6 尝试预算),第二次尝试仅允许“移除已存在 encrypted_content”的签名恢复重试(continuationRepairOnlyCipherRemoval),其余线上差异一律按 wire_* 错误拒绝;输出只含枚举/计数/SHA-256 摘要,不含凭据、正文与上游错误文本;离线 preflight(4 请求全绿才允许实跑)、SSE 解析终局语义、capture Close 冻结字节等有独立离线小测试。静态阅读,未执行,不声称任何生产验证。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "Gate stack L162-L204; grant protocol L435-L552 with fingerprint-bound turn/send grants; validateWire L737-L787 turn-2 heartbeat normalization check.", - "continuationRepairSignature L1113-L1155 excludes 401/402/403/407/429 from signature-rejection classification; offline upstream returns deterministic two-step tool/message outputs L1443-L1473.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/dto/account_edit_state_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b1f0688313749174ae098aed30b82b257571c3fc754e941e06ecd7d057a7e94c", - "review_fingerprint": "b1f0688313749174ae098aed30b82b257571c3fc754e941e06ecd7d057a7e94c", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/dto/account_mapper_cindy_probe_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a17ab47519f4eafd38a5980fcefd728cfe9eed60561632e89783522da6453ed3", - "review_fingerprint": "a17ab47519f4eafd38a5980fcefd728cfe9eed60561632e89783522da6453ed3", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "dto.AccountFromServiceShallow 对三个可空 Cindy 余额探测字段的映射测试:第一个用例证明 CindyBalanceProbeJobID/Outcome/CheckedAt 指针值被原样复制,且序列化键为 cindy_balance_probe_job_id / _outcome / _checked_at(时间按 RFC3339);第二个用例证明字段缺失时三个键仍存在并为 null(无 omitempty)。被测对象是宿主 DTO 对 cindy-provider 探测结果数据的映射层,不含探测业务规则,判为 adapter;下游相对上游为全新文件。静态阅读,未执行。", - "evidence": [ - "Full-file static review (L1-L49, EOF): artifacts/evidence/v027-claude-S52-cindy-rest-T2-review.json", - "Anchors: L12-L34 TestAccountFromServiceShallowMapsNullableCindyBalanceProbeFields (pointer equality L23-L25, JSON keys/values L31-L33); L36-L49 TestAccountFromServiceShallowKeepsMissingCindyBalanceProbeFieldsNull (keys present L43-L45, values nil L46-L48).", - "Call chain: dto/types.go:249-251 and :399-401 declare the three pointer fields with json tags and no omitempty; dto/mappers.go:279-281 and :517-519 copy them from service.Account. Probe semantics themselves live in service/cindy_balance_probe_* (S49) and plugins/cindy-provider.", - "Not claimed: no test execution; the mapper's other fields were not re-verified here." - ] - }, - { - "path": "backend/internal/handler/dto/account_mapper_redact_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2c53efa53aa7fc6cf640ef7b95a7a8c1fd8cc0eb8329f8d8a545d3d1e88799d9", - "review_fingerprint": "2c53efa53aa7fc6cf640ef7b95a7a8c1fd8cc0eb8329f8d8a545d3d1e88799d9", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "账号 DTO 脱敏测试:敏感凭据键剔除并以 has_* 状态位标示、Ollama 托管 extra 三键剔除且不改源对象。下游新增两条:codex_turn_ticket:* 状态 blob 与 codex_harvest_proxy_url(含代理密码)必须从 Extra 剔除且序列化不含其子串(判定谓词 service.IsOpenAICodexTicketPrivateExtraKey);Cindy 设备 ID 掩码为“前 8...后 8”且源对象不被改动(service.MaskCindyDeviceID)。锁定 dto 层不泄露插件域私密 extra。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L98-L122 codex ticket/harvest proxy redaction incl. JSON substring assertions; L132-L151 cindy device-id masking with source immutability.", - "L14-L61 upstream credential redaction assertions (refresh/access/id token, api_key) unchanged.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/dto/account_view_facts_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cd2654fcd06743ad1c1c7a5173541ac58173b2ad8ea2e79cd65e34473768a85d", - "review_fingerprint": "cd2654fcd06743ad1c1c7a5173541ac58173b2ad8ea2e79cd65e34473768a85d", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "全文复核native DTO投影fixture:真实canonical Cindy身份/余额标记推导七标量,Full与ListItem一致,status/plan/canonical值明确;单独序列化facts不得包含合成credentials/Extra值,错误wire反控不得保留canonical=true。纯内存方法有实际绿结果,不把该投影等同整个DTO或插件授权验收。", - "evidence": [ - "artifacts/evidence/v027-account-view-integration-review.json#verification", - "Current complete fixture read; actual targeted results reused without rerunning." - ] - }, - { - "path": "backend/internal/handler/dto/credentials_redact.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "95dbcd2730eae7d3738cfdaeca833dbb9bb280206b3e74d1576d50d54d8b8a4c", - "review_fingerprint": "95dbcd2730eae7d3738cfdaeca833dbb9bb280206b3e74d1576d50d54d8b8a4c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整审阅71行及新增RestoreAPIKey下游hunk;保留默认脱敏,只准许窄字段恢复。", - "evidence": [ - "RedactCredentials先建立独立顶层map,按敏感字段名单屏蔽值;恢复函数只接收非空string类型api_key。", - "RestoreAPIKey不恢复access_token、refresh_token、private_key等其他敏感值,不改变原始credentials map。", - "完整静态审阅对应120行测试;恢复白名单测试本轮未单独执行,未标记为通过。" - ] - }, - { - "path": "backend/internal/handler/dto/credentials_redact_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "96c71ce46bbadfe6ee584143079d982a42585e1b73631862fcecec571630a59b", - "review_fingerprint": "96c71ce46bbadfe6ee584143079d982a42585e1b73631862fcecec571630a59b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "完整静态审阅120行;本轮未执行。", - "evidence": [ - "覆盖已知敏感字段脱敏与仅恢复api_key、原输入不被修改;未添加或执行额外数据层/网络测试。" - ] - }, - { - "path": "backend/internal/handler/dto/group_mapper_profit_visibility_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "029582a487cdf62347503066db46c441ab8d6a4267a345d05534b882e2af94d7", - "review_fingerprint": "029582a487cdf62347503066db46c441ab8d6a4267a345d05534b882e2af94d7", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "分组利润控制可见性测试:普通用户 DTO(GroupFromService/Shallow)不得含三个 profit 字段但保留 rate_multiplier;下游把管理员断言从“透传存量值”改为“休眠字段固定零值但保留 JSON 形状”(TestGroupFromServiceAdminReturnsDormantProfitControlFields),与 mappers.go GroupFromServiceAdmin 的 false/0/0 固定值一致,防止存量利润配置经响应与 rate_multiplier 联合反推上游成本上限。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L63-L76 dormant zero-value assertion replacing the upstream passthrough assertion; field-presence check keeps the legacy response shape.", - "L45-L61 user-facing omission test unchanged upstream content.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/dto/mappers.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9fc4c8c65026a45f66f6ec93d77dce3832c86986742489130d48ff601d95ae5c", - "review_fingerprint": "9fc4c8c65026a45f66f6ec93d77dce3832c86986742489130d48ff601d95ae5c", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/dto/provider_identity_mapper_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8329cfb9d98e8882e70ecced8150b19e5b658a79d8c28dfc86254b02d82d398a", - "review_fingerprint": "8329cfb9d98e8882e70ecced8150b19e5b658a79d8c28dfc86254b02d82d398a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "新增测试:Account/Group DTO 暴露规范身份三轴——platform=cindy、wire_platform=openai、provider_profile=cindy_laxa_v1 经 AccountFromServiceShallow/GroupFromService 原样映射(源字段已填时 Effective* 直接透出)。锁定身份轴在 DTO 层的透出契约。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L10-L27 both mappers asserted against service constants (WirePlatformOpenAI, ProviderProfileCindyLaxaV1).", - "Mapper sites: mappers.go L251-L252 (account) and L186-L187 (group).", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/dto/settings.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "55d85dfc43bc489a932ed4fe45cf940740c7c21fe13d7e849f0d580294af29cd", - "review_fingerprint": "55d85dfc43bc489a932ed4fe45cf940740c7c21fe13d7e849f0d580294af29cd", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "完整审阅对官方baseline的全部3个下游hunk;652行未变官方DTO定义复用baseline。", - "evidence": [ - "三组Cindy兼容性响应结构只读,新增admin refusal/compatibility字段不含显示密码或ticket proxy凭据。", - "公共DTO只添加ImageStudioEnabled布尔值;沿setting_public -> CindyImageStudioFeatureEnabled -> currentImageToolsConfig核对插件为权威来源,无新增第二个持久化字段。", - "未把DTO字段存在本身误报为双写;没有运行无直接改动风险的前端或公共服务测试。" - ] - }, - { - "path": "backend/internal/handler/dto/types.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "b122a3038e4e6e750059631cf993d265bd5ff3c7b8765a93e054c50949e5afeb", - "review_fingerprint": "b122a3038e4e6e750059631cf993d265bd5ff3c7b8765a93e054c50949e5afeb", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/endpoint.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "8bd729f0b791d9a4087774dfd08610b61adcd527832a5908dd4c31c382328c86", - "review_fingerprint": "8bd729f0b791d9a4087774dfd08610b61adcd527832a5908dd4c31c382328c86", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "入站/上游端点规范化与推导的唯一常量表(358 行):NormalizeInboundEndpoint 处理裸别名路由(/responses、/backend-api/codex/...)与 compact 独立入站端点(先于根 responses 匹配),DeriveUpstreamEndpoint 按平台推导并保留 /responses 子路径后缀,GetUpstreamEndpoint 优先 OpenAI 运行时实际端点覆盖。下游相对上游:新增 EndpointModelCapabilities 常量并在 OpenAI/Cindy/Grok 分支返回空串——本地能力发现响应不得把运维遥测归因到 /v1/responses;PlatformCindy 并入 OpenAI 线协议分支。纯宿主协议机制,无插件业务。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "Diff vs aea725f: L34 new constant, L203 adds PlatformCindy to the OpenAI wire case, L207-L209 local-discovery empty upstream.", - "Alias matching anchored via isBareOrSubpathOf (L181-L183) so /foo/responses never matches; GetInboundEndpoint fallback prefers c.Request.URL.Path over wildcard-collapsing FullPath (L302-L319).", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/endpoint_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "dac4ed615c1ea988d92c2039a75c3fec8e0304a41c5e56162e10ac9768a5b6ca", - "review_fingerprint": "dac4ed615c1ea988d92c2039a75c3fec8e0304a41c5e56162e10ac9768a5b6ca", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "端点规范化/推导测试(460 行):canonical 与别名路由映射、compact 先于根 responses、不得泛化到 /foo/responses、wildcard 路由必须按请求路径而非 FullPath 归一(中间件与无中间件 fallback 双路径)、运行时上游端点覆盖优先级(Grok ForwardResult 覆盖陈旧上下文、OpenCodeGo 空结果保持入站)。下游 diff 新增两条:cindy responses 根路径按 OpenAI 线协议推导为 /v1/responses(L107);EndpointModelCapabilities 推导为空串(L133,本地服务不归因上游)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L107 and L133 are the only delta vs aea725f (2 added table rows).", - "L429-L448 fallback wildcard guard asserts FullPath returns the pattern while GetInboundEndpoint still yields EndpointResponsesCompact.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/failover_loop_profit_veto_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": false, - "content_sha256": null, - "deleted_upstream_blob": "c417c27e10424e3d4629661c0b61a932abdc2aee", - "review_fingerprint": "a9a2a128ec77c5aab6790d7c20c53b732d3482625fb7460a3da3847caf5d9d2a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "完整blob包括利润veto迭代上限、503路径不活锁、backoff后健康账号仍可选、10次cap与exclusion,以及没有profit veto时普通503清空失败集合。 专属断言随退休功能闭合;普通503清集合断言已有保留位置,删除不能解释为取消普通failover预算。", - "evidence": [ - "Exact deleted blob and replacement assertion mapping: artifacts/evidence/v027-astra-deleted-path-review.json", - "该已删文件及旧profit-preview均未运行;独立dormant证据记录限定服务回归。", - "Deletion basis: 5f216d1d07f091b8942aa70e3c5ee3d7fc4153fe", - "The bound dormant implementation is included with this review; its exact eight source SHA256 values were verified before import." - ] - }, - { - "path": "backend/internal/handler/failover_loop_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0528a2a5b0f418f7081b5b93e9ef5393f3a0d4d2e5463b7ac93479ecdfa1a36e", - "review_fingerprint": "0528a2a5b0f418f7081b5b93e9ef5393f3a0d4d2e5463b7ac93479ecdfa1a36e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "FailoverState 状态机测试(1061 行):同账号重试延迟档位(RequestScopedTransient 指数退避至 8s 封顶、显式 OAuth 延迟优先)、deadline/错误级上限/账号 pool_mode_retry_count 的重试许可、显式 NextAccountStop 不切换、入口已取消不改动任何 failover 状态(#4257:客户端断开不得转成 502)、ForceCacheBilling 单向置位、TempUnschedule 仅在同账号重试耗尽时调用、HandleSelectionExhausted 的 503 等待重试并清失败列表、failoverClientGone 的 499 标记与已提交响应不覆盖。下游 diff 新增“会话状态失效不切换账号也不临时封禁”(L241-L258):NewOpenAIContinuationStateUnavailableError 直接 FailoverExhausted,不计切换、不进失败列表、不 TempUnschedule——防止 previous_response 缺失把健康账号连坐处置。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "New case L241-L258 asserts zero SwitchCount/FailedAccountIDs/SameAccountRetryCount/mock.calls for the continuation-state error.", - "Cancellation invariants L642-L702 and selection-exhausted semantics L925-L1017 are upstream content read in full.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/gateway_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "47dfccfdd0a4c6a0966a791b77a587dc3b64a3a270fa0205fdd5e33406bac7e6", - "review_fingerprint": "47dfccfdd0a4c6a0966a791b77a587dc3b64a3a270fa0205fdd5e33406bac7e6", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/gateway_handler_chat_completions.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "69ee1f48fb973a646dedc003c35e294dd5176455f29335c6f6bd5174e2175123", - "review_fingerprint": "69ee1f48fb973a646dedc003c35e294dd5176455f29335c6f6bd5174e2175123", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "/v1/chat/completions 在 Anthropic/Gemini/Antigravity 分组上的兼容入口(413 行):鉴权、gjson 校验、composite 目标平台解析、GPT 生图模型拒绝、ClaudeCodeOnly 403、安全审计、并发槽、利润门终检+准入后绑定、渠道映射仅作用于 forwardBody(不污染原始 body)、Gemini 分组下非 Gemini 账号跳过、failover 环与 usage 异步提交。下游相对上游仅在 handleCCFailoverExhausted 增加 IsOpenAIModelNotSupported → 400 + service.OpenAIModelNotSupportedCode 标准映射(L391-L394,与 responses 侧对称)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "Diff vs aea725f is the 4-line model-not-supported branch; remaining exhausted mapping (credential failure, capacity shed, silent refusal, Retry-After copy) is upstream content.", - "setActualUpstreamEndpoint(c, \"\") reset before each forward (L269) then Antigravity compat pins EndpointAntigravityGenerateContent (L287).", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/gateway_handler_responses.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3e39ed500a25e77204343eb3771301aa49ec12993acd22b44e55d7d4fccd76dc", - "review_fingerprint": "3e39ed500a25e77204343eb3771301aa49ec12993acd22b44e55d7d4fccd76dc", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "/v1/responses 在 Anthropic 系分组上的兼容入口(404 行):结构与 chat_completions 对称;另有生图意图上下文(token 计费与利润门不因工具声明关闭,L95-L103)、利润门必须用选号结果携带的门而非 requestCtx(L232-L235 注释)、流已开始时的终止帧语义(仅心跳时补 response.failed,已有语义字节则不追加第二个终止帧,L392-L402)。下游相对上游仅在 handleResponsesFailoverExhausted 增加 IsOpenAIModelNotSupported → 400 标准映射(L378-L379)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "Diff vs aea725f is the 2-line model-not-supported else-if; 429 exhaustion mapped to rate_limit_error with retry hint (L389-L391, upstream content).", - "Usage submission captures endpoint/UA/IP before the async task; RecordUsage keyed to the final forwarded body hash of the original body (L321).", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/gateway_model_capacity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7403169eb04c1ab4d204734ada9c89a450f3b425c7657fd646a0a370152c1ef4", - "review_fingerprint": "7403169eb04c1ab4d204734ada9c89a450f3b425c7657fd646a0a370152c1ef4", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增测试:/v1/models 上下文容量投影。断言 allowlist 顺序与别名保持(alias-b/alias-a 保序输出)、账号 extra 的 ModelContextOverrides 投影为 context_window=650001 且 context_capacity_source=custom、响应不含 created_at/account_id;账号候选查询失败时列表保留(Gemini 默认 200000)并给 context_capacity_reason=account_query_failed,内部错误文本不外漏;候选查询恰调用一次。锁定 Models 的 ProjectModelListContextCapacities 投影契约(core 容量机制)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S04-handler-rest-1-review.json", - "L31-L63 shape/alias/order/override assertions incl. leak checks; L65-L87 failure path keeps the list and hides the error string.", - "Projector wired via modelCapacityProjectorContextKey in gateway_handler.go L1174-L1176 and applied in writePublicModelsJSON L1406-L1419.", - "Statically reviewed only; no test, build, network or production access." - ] - }, - { - "path": "backend/internal/handler/gateway_models_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8a9ac65f95fb91c1cc4b5e4e4cfc47db8fcb33c597adcde5cd547b7b85dd1a21", - "review_fingerprint": "8a9ac65f95fb91c1cc4b5e4e4cfc47db8fcb33c597adcde5cd547b7b85dd1a21", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/grok_media.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3e59790ddf5eb4a98eaecc541423a282ef9a57c47aec3d5f8d9baaa77570ac52", - "review_fingerprint": "3e59790ddf5eb4a98eaecc541423a282ef9a57c47aec3d5f8d9baaa77570ac52", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Grok/Seedance 图像与视频网关转发主循环(847 行,上游已有)。下游相对上游做三类改动:1) 把手写 sameAccountRetryCount 换成共享 openAIFailoverRetryState.Handle + ReacquireOpenAISameAccountSelection + finalizeOpenAIFailoverSelection + failoverAfterSameAccountSlotFailure 框架(与全部 OpenAI 协议 handler 一致);2) 新增 sync.Once 包装的 releaseSelection,在 client-gone、绑定账号不符、资格拒绝等早退路径释放已占账号槽与 runtime breaker 探针,资格探测挂 requestCtx.Done 取消释放并以 probeDone/probeStopped 顺序转移槽所有权;3) 绑定的视频查询(boundLookupAccountID>0)不再重生成 pool 会话哈希以保护任务属主绑定;BindGrokMediaVideoRequestAccount 触发条件由 isGrokVideoCreateEndpoint 放宽为 IsGenerationRequest。全部是网关调度/failover/并发槽通用机制,无插件业务规则;媒体计费与视频 pending 计费为上游已有逻辑。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta vs aea725f: 116 insertions/53 deletions — retryState at L200, releaseSelection sync.Once L315-L326, probe cancellation goroutine L352-L368, bound-lookup hash skip L395-L397, same-account slot reacquire L405-L409 plus failoverAfterSameAccountSlotFailure L420-L427, finalizeOpenAIFailoverSelection at L462/L467/L472/L486, ReportOpenAIAccountScheduleResultForSelection replaces ReportOpenAIAccountScheduleResult (L518/L529).", - "Double-release safety verified: selection.ReleaseFunc is wrapped by wrapReleaseOnDone (gateway_helper.go L188-L202, sync.Once inside), so releaseSelection plus top-of-loop releaseAccount() on the same underlying func cannot double-release.", - "Shared framework confirmed: newOpenAIFailoverRetryState/ReacquireOpenAISameAccountSelection also used by openai_alpha_search.go, openai_chat_completions.go, openai_codex_models_handler.go, openai_embeddings.go, openai_gateway_count_tokens.go, openai_gateway_handler.go, openai_images.go (openai_failover_retry.go L137-L260).", - "No production behavior edit or test execution; review is static only." - ] - }, - { - "path": "backend/internal/handler/handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d748ca089aede46505177f0e576e0212dfb6d15a2783a08e34f45d13d6de8ee6", - "review_fingerprint": "d748ca089aede46505177f0e576e0212dfb6d15a2783a08e34f45d13d6de8ee6", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "Shared handler structs add only host endpoint references for jobs, prompt management, Cindy probe, media and skills. They contain no business policy, credential return logic or auth routing; those stay in their named implementations/routes. Existing official handlers remain in the struct.", - "evidence": [ - "Full file and official v0.2.7 delta read; fields are wired explicitly in handler/wire.go.", - "artifacts/evidence/v027-host-job-wiring-static-review.json" - ] - }, - { - "path": "backend/internal/handler/image_studio_executor.go", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "e87e12b120b1e1b5afaefa6a7a9923a4f12bc1f4ce6bf6a8fc180668cf001c47", - "review_fingerprint": "e87e12b120b1e1b5afaefa6a7a9923a4f12bc1f4ce6bf6a8fc180668cf001c47", - "review_status": "reviewed", - "decision": "adapter", - "owner": "image-tools", - "reason": "Image Studio 作业执行器(184 行,下游新文件,整文件即增量)。Execute 先经 service.PlanImageStudioExecution 取得插件规划(extensionv1.ImageStudioPlan),据此构造 JSON(generate)或 multipart(edit,含 reference/mask 文件)请求,用 httptest 合成 gin 上下文在进程内复用核心 /v1/images 网关(e.images.Images(c)),并回填 API key/AuthSubject/订阅上下文(订阅分组缺订阅即拒绝);响应解码强制 base64 解码尺寸不超过 ImageStudioMaxImageBytes 且 PNG/JPEG/WEBP 魔数校验,网关非 200 时只返回笼统错误不透传上游 body。模型/尺寸/质量/端点等业务规则在 image-tools 插件(service/plugin_image_tools.go 桥接),此文件是宿主到核心网关的执行胶水,归 adapter/image-tools。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "New downstream file: git ls-tree aea725f -- prints nothing; whole file is the delta.", - "Plan source: service.PlanImageStudioExecution (backend/internal/service/plugin_image_tools.go L103) returns extensionv1.ImageStudioPlan; executor wired in backend/internal/handler/wire.go L271 (NewImageStudioGatewayExecutor).", - "Boundary checks read: n comes from plan.OutputPerRequest (native n=1), decodeImageStudioGatewayResponse enforces DecodedLen cap (L157) and magic-number content type (L173-L184); upstream error bodies are not propagated (L77-L79).", - "No production behavior edit or test execution; review is static only." - ] - }, - { - "path": "backend/internal/handler/image_studio_executor_test.go", - "candidate_owner": "image-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "137ed390fdb2022e3808501d429edafdaec8c548fa3441edc864150d013c2df0", - "review_fingerprint": "137ed390fdb2022e3808501d429edafdaec8c548fa3441edc864150d013c2df0", - "review_status": "reviewed", - "decision": "adapter", - "owner": "image-tools", - "reason": "执行器桥接测试(132 行,下游新文件)。断言:generate 走 /v1/images/generations、JSON 体且原生 n=1(Count=4 也只请求 1 张);edit 走 multipart 携带 image 与 mask 原始字节;上游 502 错误体不外泄到 err(NotContains private upstream body);订阅分组经 GetActiveSubscription 把订阅注入 gin 上下文保持计费口径。被测对象是宿主桥接层(ImageStudioGatewayExecutor),规则归 image-tools 插件;用 enableImageStudioPolicy(t) 挂测试目录。测试为静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Assertions anchored: native n=1 for generate L39-L60, multipart edit with mask L62-L92, upstream error body suppression L94-L105, subscription context preservation L115-L132.", - "Subject is the in-process gateway bridge, not plugin business rules; stubs (imageStudioImagesInvokerFunc, imageStudioSubscriptionFinderStub) replace core services.", - "New downstream file (absent from aea725f); test not executed (static read only)." - ] - }, - { - "path": "backend/internal/handler/image_studio_job_handler.go", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "6c7f703cddd5701017e9c61bc68b0e17aa911c9cb099b282b7bb1cbef15dadeb", - "review_fingerprint": "6c7f703cddd5701017e9c61bc68b0e17aa911c9cb099b282b7bb1cbef15dadeb", - "review_status": "reviewed", - "decision": "adapter", - "owner": "image-tools", - "reason": "Image Studio 作业 REST 接口(315 行,下游新文件):eligible-keys/创建/列表/详情/条目/取消/重试/工件下载。所有操作经 authorize/ownerAndJobID 把会话用户 ID 作为属主传给 service 层(Create 的 userID 取自 AuthSubject 而非表单),jobID/artifactID 非法一律 404;上传受 MaxBytesReader(2*20MB+1MB) 与单文件 ImageStudioMaxImageBytes 上限约束(io.LimitReader 双重校验);工件下载设置 Cache-Control private no-store、X-Content-Type-Options nosniff、attachment 文件名;错误经 imageStudioJobError 映射 ImageStudioError/ErrImageStudioNotFound 等为稳定状态码。业务规则在 service.ImageStudioService 与 image-tools 插件(EnsureImageStudioAvailable 特性门),此处只有鉴权、参数校验与 DTO 映射,归 adapter/image-tools。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "New downstream file (absent from aea725f); whole file is the delta.", - "Owner binding anchors: authorize L216-L227 (AuthSubject.UserID), ownerAndJobID L229-L240, Create passes session userID L91; artifact headers L207-L211; upload limits L68-L69 and L242-L260.", - "Feature gate: service.EnsureImageStudioAvailable (backend/internal/service/plugin_image_tools.go L68) consulted on Create/Retry/EligibleKeys; handler wired via wire.go L270.", - "No production behavior edit or test execution; review is static only." - ] - }, - { - "path": "backend/internal/handler/image_studio_job_handler_test.go", - "candidate_owner": "image-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3a56f7361f08261a67a7dda3041911830ceee1a1ddc4c150a62c6f9eb4a0e2dc", - "review_fingerprint": "3a56f7361f08261a67a7dda3041911830ceee1a1ddc4c150a62c6f9eb4a0e2dc", - "review_status": "reviewed", - "decision": "adapter", - "owner": "image-tools", - "reason": "作业 REST 接口测试(126 行,下游新文件)。断言:eligible-keys 响应不含 key 明文(NotContains server-only-secret 与 \"key\" 字段);创建返回 202 且属主取会话 UserID=7 而非表单、api_key_id/count/reference 正确解析且缺省 mask 为 nil;工件下载 200 且带 private no-store 头并回放原始字节;无会话返回 401。用 imageStudioHandlerServiceStub 替代 ImageStudioService,只证明宿主适配层行为,规则归 image-tools。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Assertions anchored: secret non-exposure L68-L78, session-owner create L80-L103, artifact headers/bytes L105-L117, unauthorized L119-L126.", - "Stub-based: no ImageStudioService business rule is exercised; enableImageStudioPolicy(t) mounts the plugin policy fixture (plugin_contract_fixture_test.go).", - "New downstream file (absent from aea725f); test not executed (static read only)." - ] - }, - { - "path": "backend/internal/handler/no_account_error.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "62c1dbd4f04e8f62f92b39cc30c095f081a1980218d849369ef9bdf24574c23f", - "review_fingerprint": "62c1dbd4f04e8f62f92b39cc30c095f081a1980218d849369ef9bdf24574c23f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "无可用账号错误分类器(195 行,上游已有):经 DiagnoseModelAvailabilityForPlatform 的持久化判据在 404 model_not_found / 503 api_error / 429 rate_limit_error 之间裁决。下游相对上游新增两处:1) ModelNotSupportedCooldownExhausted(所有支持该模型的账号都处于 model_not_supported 冷却)时返回结构化 400 model_not_supported(L125-L131);2) classifySelectionFailureError 增加 fallback.ErrType==OpenAIModelNotSupportedCode 守卫(L59),防止该 400 被 429 限流改判覆盖。属网关协议错误分类通用机制,无插件业务规则。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta vs aea725f: 9 insertions/1 deletion — the ModelNotSupportedCooldownExhausted branch (L125-L131) and the OpenAIModelNotSupportedCode guard in classifySelectionFailureError (L59).", - "Diagnosis source traced: ModelNotSupportedCooldownExhausted set in backend/internal/service/openai_gateway_model_availability.go L74 (supportingAccounts>0 and all in model_not_supported cooldown); code/message constants in service/openai_model_not_supported.go L30-L31.", - "Callers traced: classifyNoAccountErrorFromGin marks OpsClientBusinessLimitedReasonLocalModelConfiguration only for 404 (L159-L162); grok_media.go and other OpenAI handlers gate markOpsRoutingCapacityLimitedIfNoAvailable on ModelNotFound.", - "No production behavior edit or test execution; review is static only." - ] - }, - { - "path": "backend/internal/handler/no_account_error_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e9ffc50f7fc87b84cbad1038611867e98e8ad3a2f68d5943fdaa20dff4cd6b11", - "review_fingerprint": "e9ffc50f7fc87b84cbad1038611867e98e8ad3a2f68d5943fdaa20dff4cd6b11", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "分类器单测(325 行,go:build unit,上游已有)。下游相对上游仅新增 TestClassifyNoAccountError_ModelNotSupportedCooldownExhaustedReturnsStructured400(L188-L206):锁定诊断 ModelNotSupportedCooldownExhausted=true 时返回 400 model_not_supported,且经真实调用链 classifySelectionFailureError(错误串含 model_rate_limited=2)后不被 429 覆盖。上游已有断言覆盖 nil 防御、404 归因 ops 标记、404 不被 429 盖、显示模型与路由模型分离。被测对象为核心网关机制。测试为静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta vs aea725f: 20 insertions — exactly the one new test at L188-L206 proving the structured 400 survives the classifySelectionFailureError chain.", - "The test mirrors real call-site order (classifyNoAccountErrorFromGin then classifySelectionFailureError), same chain as production call sites, e.g. grok_media.go L285-L289.", - "Static read only; the test was not executed." - ] - }, - { - "path": "backend/internal/handler/openai_alpha_search.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "19aaf32746819eddf5914f9d69741e4509ae1a60eac116eedded945b6ef98df5", - "review_fingerprint": "19aaf32746819eddf5914f9d69741e4509ae1a60eac116eedded945b6ef98df5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Codex /v1/alpha/search 独立搜索入口的宿主处理器:鉴权、请求体校验、渠道模型映射、计费资格、调度选号、failover 循环与按次用量落库。下游相对上游 aea725f 新增 Cindy 分组准入(ClassifyCindyIdentityGroup、CindySearchFeatureEnabled、ResolveCindyAlphaSearchPlan 均经 service 桥接:cindy_alpha_search_plan.go 调用扩展操作 cindy.search.plan,feature flag 读插件配置,处理器本身不复刻搜索规则),同账号重试改为 openAIFailoverRetryState + ReacquireOpenAISameAccountSelection,新增 trafficObserver 观测、finalizeOpenAIFailoverSelection 探针收尾和 requestPlatform 取代硬编码 PlatformOpenAI,用量改用 snapshotOpenAIUsageMetadataWithHash。归宿主网关机制;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L32-L52 and L97-L110: Cindy gating only delegates (h.gatewayService.ClassifyCindyIdentityGroup, service.CindySearchFeatureEnabled, service.ResolveCindyAlphaSearchPlan); service/cindy_alpha_search_plan.go L25-L48 forwards to invokeProcessExtensionCached(Operation cindy.search.plan), so no second executor of the search plan lives in this handler.", - "L166-L334 failover loop: failedAccountIDs keyed by the selected account.ID (L317), failoverClientGone checked before classification (L190) and after failover error (L282, releases runtime breaker probe only, deliberately no schedule failure report for client aborts), retryState.Handle returns openAIFailoverRetryCanceled on ctx.Done; accountRelease deferred inside the forward closure together with trafficTurn.Finish (L245-L253). Non-streaming endpoint (stream=false everywhere), so no SSE cleanup path.", - "L340-L379 recordAlphaSearchUsage captures apiKey.ID/GroupID/account.ID before the async mandatory task and uses OpenAIPricingAtFromContext; L381-L396 resolveOpenAIAlphaSearchUpstreamEndpoint prefers result.UpstreamEndpoint (bridge vs direct).", - "Diff vs aea725f: +PlatformCindy admission, +Cindy pins channelMapping.Mapped=false (L121-L128) so channel mappings cannot expose the hidden fallback model, -inline sameAccountRetryCount loop, -pkg/ip import (moved into snapshot helper), ReportOpenAIAccountScheduleResult -> ...ForSelection.", - "No production behavior edit or test execution; static review only." - ] - }, - { - "path": "backend/internal/handler/openai_alpha_search_bridge_error_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "70ee4c1cd866d933cba54717443b86d7e954d469309307609e9d1958548641af", - "review_fingerprint": "70ee4c1cd866d933cba54717443b86d7e954d469309307609e9d1958548641af", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增(上游无此文件)的 handler 错误收敛测试,静态阅读未执行。三条断言:handleFailoverExhausted 对 NewOpenAIAlphaSearchBridgeUnavailableError 统一返回 503 server_error/web_search_unavailable/retryable:true 且不泄露上游 body;CindyBalanceInsufficient 的 429 绕过 error passthrough 规则(规则匹配 budget_exceeded 也只回通用 'Upstream rate limit exceeded',不泄露 fixture-account);resolveOpenAIAlphaSearchUpstreamEndpoint 区分直连 alpha/search 与 responses 桥接。被测主体是宿主 handler 的脱敏映射,Cindy 余额标志由 service 层消毒后传入,测试不涉及插件规则本身。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L37-L60 TestOpenAIAlphaSearchBridgeFailoverExhaustionReturnsSafeRetryableError: exact JSONEq on the 503 envelope and NotContains 'must-not-leak'.", - "L62-L94 TestCindyBalanceFailoverBypassesErrorPassthrough: builds a real service.NewErrorPassthroughService with an in-memory rule repo (L15-L35) whose rule would pass the raw body through; asserts 429 with generic message, proving the CindyBalanceInsufficient short-circuit in handleFailoverExhausted.", - "L96-L112: EndpointAlphaSearch when result has no UpstreamEndpoint, EndpointResponses when the bridge reported it, and fallback after clearing the actual-endpoint context.", - "New downstream file (git ls-tree aea725f prints nothing); not executed." - ] - }, - { - "path": "backend/internal/handler/openai_alpha_search_cindy_gate_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a296018ec4bdc097b0414564f6245176f0667ac596473059e4b0a1cf27999481", - "review_fingerprint": "a296018ec4bdc097b0414564f6245176f0667ac596473059e4b0a1cf27999481", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "仅在 `unit` 构建标签下编译的 /v1/alpha/search Cindy 门禁测试。第一个用例以子进程重跑自身(目录=true、搜索=false、HELPER 标记)并断言:对声明为 Cindy 身份的组(Platform=cindy、WirePlatform=openai、ProviderProfile=laxa-v1),handler 在取 auth subject 和 ensureResponsesDependencies 之前就返回 404 `model_not_found`——此时 handler 的 billing/concurrency 依赖全为 nil,任何越过门禁的路径都会 500/panic,因此该断言实际证明了门禁顺序。第二个用例在特性开启(TestMain 重启)下断言 CindyWebSearchModel、CindyAutoReviewModel 和已移除的 gemini-3-pro-image 在账号选择前被 ResolveCindyAlphaSearchPlan(经扩展调用到 cindy-provider 插件的 AlphaSearchPlan)判为不允许并返回 404。被测对象是宿主对插件搜索开关与搜索计划的门禁胶水,允许/拒绝规则本体在插件,判为 adapter;下游相对上游为全新文件。静态阅读,未执行。", - "evidence": [ - "Full-file static review (L1-L97, EOF): artifacts/evidence/v027-claude-S52-cindy-rest-T2-review.json; build constraint `//go:build unit` at L1.", - "Anchors: L22-L46 subprocess case (env filtered by withoutHandlerEnvironmentKeys L84-L97, catalog=true/search=false, -test.run pinned) asserting 404 + `\"type\":\"model_not_found\"` with no user in context; L48-L61 table over service.CindyWebSearchModel/CindyAutoReviewModel/gemini-3-pro-image with user set, same 404; L63-L82 fixture group declares PlatformCindy + WirePlatformOpenAI + ProviderProfileCindyLaxaV1 and a nil-repo OpenAIGatewayService.", - "Call chain: handler/openai_alpha_search.go:21 AlphaSearch -> :38 ClassifyCindyIdentityGroup -> service/cindy_group.go:148-155 returns identity from group declaration without repository; :49-52 `!service.CindySearchFeatureEnabled()` 404 precedes GetAuthSubjectFromContext (:53) and ensureResponsesDependencies (:65/:108); :98 ResolveCindyAlphaSearchPlan (service/cindy_alpha_search_plan.go:25/:40 invokeProcessExtensionCached -> plugins/cindy-provider catalog AlphaSearchPlan) -> :103 `!plan.Allowed` 404 before SelectAccountWithSchedulerForCapability (:175). Search flag read via service/cindy_feature_flags.go:68 from plugin config seeded by testextensions (LegacyCindyProviderConfig).", - "Not claimed: not executed; whether CI passes `-tags unit` was not checked. Minor note: withoutHandlerEnvironmentKeys duplicates withoutCindyCatalogHandlerEnv (cindy_catalog_rollback_test.go L283) in the same package." - ] - }, - { - "path": "backend/internal/handler/openai_automation_bootstrap_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4fcb5f1fd7d21f6a3ab98446658f8e560923b71baafcc35383aefce3cf2b35bb", - "review_fingerprint": "4fcb5f1fd7d21f6a3ab98446658f8e560923b71baafcc35383aefce3cf2b35bb", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Codex 客户端 automation 引导/心跳输出规范化(normalizeCodexAutomationBootstrap、validCodexAutomationHeartbeat、对照 normalizeCodexDelegationBootstrap)的单元测试。这些函数在上游 aea725f 的 openai_gateway_handler.go 已存在(上游 L1644/L1651/L1890),属网关协议兼容机制而非插件业务;plugins/codex-runtime 下 rg 无 automation_update/heartbeat 实现,不构成第二执行者。下游相对上游新增:带 current_time_iso+instructions 的完整心跳、空/缺失 call_id、CRLF 与转义实体、39 轮历史中的多个心跳、服务端工具历史(web_search/file_search/code_interpreter/image_generation/mcp/server tool_search)对 automation 放行而 delegation 不放行、以及更多拒绝形状(重复字段、命名空间/属性、无时区时间戳、错误 memory 路径)。断言证明结果为 role=user/input_text 消息、幂等、其余字段 Raw 原样保留。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f: +automationHeartbeat const, TestNormalizeCodexAutomationBootstrapHeartbeat becomes table-driven (L54-L83), +TestNormalizeCodexAutomationBootstrapWithLongHistoricalContext (L231-L292) and +TestNormalizeCodexAutomationBootstrapWithServerToolHistory (L294-L365), rejected-shape tables extended (L85-L229); two old cases ('previous response', 'real call context') replaced by 'non-string previous response' and 'ambiguous call context'.", - "Subject functions live in backend/internal/handler/openai_gateway_handler.go (current L2066/L2073/L2355) and already existed upstream; rg --no-config over plugins/codex-runtime finds no duplicate normalizer.", - "Idempotence asserted after every positive case (again/changedAgain), and L399-L411 direct validCodexAutomationHeartbeat negatives.", - "Not executed; static read only." - ] - }, - { - "path": "backend/internal/handler/openai_body_limit_failover_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5452b788b3d206638919a56c91a4e7c1a4c167a54916433d2cbe3b6152547ddc", - "review_fingerprint": "5452b788b3d206638919a56c91a4e7c1a4c167a54916433d2cbe3b6152547ddc", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "handleFailoverExhausted 客户端错误收敛测试。上游已有 413 请求体过大的 JSON/SSE 脱敏两例;下游新增三例:continuation_state_unavailable 返回终态 400(JSON 与 event: response.failed SSE,均不带 retryable:true、不泄露上游 message),upstream_400_model_not_supported 返回结构化 400(type/code 均为 model_not_supported,固定客户端文案)。被测主体是宿主网关错误映射;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f adds L49-L102 (three tests) and L116-L122 continuationStateFailoverTestError built from service.NewOpenAIContinuationStateUnavailableError with a leaking upstream body.", - "Assertions: status codes 413/400, error.type invalid_request_error or OpenAIModelNotSupportedCode, error.code equals service constants, NotContains 'must-not-leak' and NotContains '\"retryable\":true' for the terminal SSE case (L80).", - "Handler under test constructed as zero-value &OpenAIGatewayHandler{}, so only the pure mapping in handleFailoverExhausted is exercised.", - "Not executed; static read only." - ] - }, - { - "path": "backend/internal/handler/openai_chat_completions.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "b3c2ab8f6ff366eab5ff974e76ecb3c07bd7d02460e6ca969cb52921a38b78e9", - "review_fingerprint": "b3c2ab8f6ff366eab5ff974e76ecb3c07bd7d02460e6ca969cb52921a38b78e9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "POST /v1/chat/completions 宿主入口:鉴权、宽松 JSON 读取、model/stream/service_tier 校验、审计与 cyber 封禁、渠道映射、用户/账号并发槽、计费资格、调度循环、失败切换与用量落库。下游相对上游新增:官方 HTTP failover 上下文标记(WithOpenAIOfficialHTTPFailover,HandleHTTP/finalizeOpenAIHTTPFailoverSelection 走 openai_official_http_failover.go)、Cindy 兼容别名路由(CindyCompatibilityMappedUpstreamModel + ClassifyCindyIdentityGroup + strictCindyModelAllowed 均调用 service 桥接,不在此复刻目录规则)、同账号重试改为 openAIFailoverRetryState + ReacquireOpenAISameAccountSelection、trafficObserver、cyber 封禁键改为 CyberSessionBlockKey、用量改为 snapshotOpenAIUsageMetadata 且仅当 shouldSubmitOpenAIUsage 为真才提交。发现一处低危:部分图片结果 + 错误的提前 return 未收尾探针/调度上报(见 findings)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L84-L102 Cindy alias/strict checks delegate to service (CindyCompatibilityMappedUpstreamModel in service/cindy_capability_catalog.go which is an extensionapi/v1 bridge; strictCindyModelAllowed defined in openai_gateway_handler.go L399); L141-L145 alias forces forwardMapped to the compatibility upstream model.", - "L191-L460 loop: failoverClientGone at loop head (L192) and after failover error (L359, releases breaker probe); accountReleaseFunc and trafficTurn.Finish deferred inside the forward closure (L298-L306); failedAccountIDs keyed by account.ID; retryState.HandleHTTP returns Canceled on ctx.Done.", - "Usage: L325-L347 snapshot captures usageInput.APIKey.ID/Account.ID before submitOpenAIUsageRecordTask; L452 shouldSubmitOpenAIUsage gate replaces upstream's unconditional submitChatUsage (upstream also billed partial results returned with an error).", - "Finding recorded: L348-L356 partial-error branch with result.ImageCount>0 returns early without ReportOpenAIAccountScheduleResultForSelection/ReleaseOpenAIRuntimeBreakerProbeForSelection (low severity).", - "Diff vs aea725f also moves logRequestBodyReadFailure before the 413 branch (L54) and routes no-account errors through handleOpenAINoAccountError (L240/L256). No test execution." - ] - }, - { - "path": "backend/internal/handler/openai_cindy_http_wsv2_sticky_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8f63a83e3627e48c679ec9aa21fadd0722f1b58114a5be668605bed2d26cd746", - "review_fingerprint": "8f63a83e3627e48c679ec9aa21fadd0722f1b58114a5be668605bed2d26cd746", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Cindy HTTP→WSv2 桥首轮握手失败时的粘性会话与调度上报测试,用内存 AccountRepository/GatewayCache 桩和真实 NewOpenAIGatewayService(simple 模式)。四个断言分别证明:(1) 首轮 502 账号级失败后 clearCindyHTTPToWSV2StickyBeforeAccountSwitch 清掉 session→A 的绑定,排除 A 后选到 B 并重新绑定,随后不带排除的重连仍落到 B;(2) 清理是“匹配才删”(DeleteSessionAccountIDIfMatches),并发已改绑到 B 时不被误删;(3) 已向客户端写出语义输出(openAIResponseHasSemanticWrite)时不清理;(4) finalizeOpenAIFailoverSelection 对 SuppressAccountHealthPenalty 的请求级终止只释放熔断探针、不上报调度失败也不计同账号重试,并用账号级 502 作反例证明上报器确实被观察。这些是宿主网关的传输失败切换/粘性会话机制(标志在 service/openai_cindy_http_wsv2.go 设置),不含目录/计价/身份等插件规则,判为 core-mechanism;下游相对上游为全新文件。静态阅读,未执行。", - "evidence": [ - "Full-file static review (L1-L262, EOF): artifacts/evidence/v027-claude-S52-cindy-rest-T2-review.json", - "Anchors: L17-L85 repo/cache doubles (cache keyed by groupID+sessionHash, accountID() reads the `openai:`-prefixed key); L87-L92 real OpenAIGatewayService with RunModeSimple; L116-L151 handshake-502 clear + exclusion reselect + reconnect assertions; L153-L173 concurrent rebind preserved; L175-L196 semantic output written -> binding kept; L198-L262 reporter double and SuppressAccountHealthPenalty vs account-scope negative control.", - "Call chain: handler/openai_failover_retry.go:92 clearCindyHTTPToWSV2StickyBeforeAccountSwitch (requires failoverErr.CindyHTTPToWSV2FirstTurn and !openAIResponseHasSemanticWrite, then gatewayService.ClearOpenAIStickySessionAccountIDIfMatches); flag set at service/openai_cindy_http_wsv2.go:123, SuppressAccountHealthPenalty set at :84/:238/:309 and in generic upstream error paths (openai_gateway_upstream_errors.go:540/574); handler/openai_failover_retry.go:176 finalizeOpenAIFailoverSelection branches on ShouldReportAccountScheduleFailure and otherwise ReleaseOpenAIRuntimeBreakerProbeForSelection. No plugins/cindy-provider counterpart for sticky-session handling was found.", - "Not claimed: not executed; the WSv2 bridge itself (service/openai_cindy_http_wsv2.go) is outside this slice and was only consulted for flag provenance." - ] - }, - { - "path": "backend/internal/handler/openai_codex_models_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "dbe5f4d0938102fef09239a2197cc1a6e75171473c811d3f9f460f0088b572fc", - "review_fingerprint": "dbe5f4d0938102fef09239a2197cc1a6e75171473c811d3f9f460f0088b572fc", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Codex CLI/桌面端 GET /models 与 /backend-api/codex/models 的 manifest 发现处理器:固定账号拉取、分组本地生成、调度器拉取 + failover、ETag 处理。下游相对上游新增 Cindy 分组支持:ResolveCindyCodexModelsScope 决定 CatalogOnly(本地生成 manifest,不触上游)或 MergeCatalog(按 OrdinaryAccountIDs 顺序只用普通账号拉取后合并 Cindy 目录),ValidateCindyCodexClientVersion 返回 426;调度改用 SelectAccountWithSchedulerForCapability + 并发槽 + openAIFailoverRetryState 同账号重试,失败经 NormalizeCodexModelsManifestFailoverError 归一并 finalize 探针;新增 projectCodexModelContextCapacities(Composite 走 nativeAnthropicGatewayService)。已按 63a98c8cc 之后的当前字节复审:CatalogOnly/MergeCatalog 改用 cindyScope.CatalogSnapshot 固定的目录快照(BuildCindyCodexModelsManifestSnapshot / MergeCindyCodexModelsManifestSnapshot),manifest 与本请求 scope 解析同源,请求中途目录刷新不再造成混排。Cindy 目录与容量规则由 service 层(扩展桥接)提供,处理器只做编排,归宿主网关机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L33-L56 platform gate extended to PlatformCindy; cindyScope from h.gatewayService.ResolveCindyCodexModelsScope (service/cindy_group.go); CatalogOnly path writes service.BuildCindyCodexModelsManifestSnapshot(cindyScope.CatalogSnapshot, If-None-Match) and returns before any account selection (post-63a98c8cc bytes, self-computed sha256 dbe5f4d09381...).", - "L119-L131 failedAccountIDs seeded with cindyScope.ExcludedAccountIDs; advanceMixedOrdinaryAccount walks OrdinaryAccountIDs in order; L185-L190 a scheduler pick that is not the expected ordinary account is excluded and its breaker probe released before continuing; MergeCatalog path now calls MergeCindyCodexModelsManifestSnapshot(manifest, \"\", cindyScope.CatalogSnapshot).", - "L139-L304 loop: every early return after a selection releases the probe or reports success (ReportOpenAIAccountScheduleResultForSelection at the end); c.Request.Context().Err() checked before writing.", - "Delta since my sequential read reviewed via git diff 63a98c8cc~1..worktree (63a98c8cc~1 blob sha d25dae97b2a6... equals the previously read bytes): exactly the two snapshot-call replacements above, nothing else.", - "No test execution; static review only." - ] - }, - { - "path": "backend/internal/handler/openai_codex_models_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2430d3a05f862531f1f8c86c37e001bbedbf517f0a10cc372a72f5c52ddc6290", - "review_fingerprint": "2430d3a05f862531f1f8c86c37e001bbedbf517f0a10cc372a72f5c52ddc6290", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "CodexModels 处理器测试(1276 行,静态阅读未执行)。断言覆盖:已取消请求不写响应;严格 Cindy 分组只出本地目录(upstream.calls 为空,slug 列表精确匹配 9 个公开模型,禁止泄露 gpt-5.4/cindy/web-search 等 ID,client_version 0.146.0 返回 426 并提及最低版本);Cindy 分组不并入普通供应商模型且两次请求结果一致;catalog 开启时非 Cindy 分组仍补全 legacy manifest 字段;本地过滤先于客户端 ETag(304 语义);API key 缓存在并发下不泄露分组过滤;未映射账号默认模型补充、spark 影子账号;404/405/429/5xx/传输错误/无效信封触发切换而 400/401/403/600/配置错误不切换;保留最后上游错误;切换上限;固定账号模式(并集、限流账号仍用、跳过不可用、部分失败仍成功、全部不可用 503、全部失败 502、回退调度器、自定义列表过滤、ETag 304)。下游相对上游新增 Cindy 三例并用 runCodexCatalogEnabledHandlerTest 以子进程 + 环境变量隔离运行,404/405 并入可重试表,requireCompleteCodexModelsHandlerResponse 放宽为多模型查找,固定账号 handler 注入 nativeAnthropicGatewayService。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f: +L152-L397 (three Cindy/catalog tests, subprocess helper L336-L364 re-executing os.Args[0] with CindyCapabilityCatalogEnabledEnv/ImageStudioEnabledEnv set, decodeCodexModelSlugs, assertCodexManifestOmitsNonResponsesCindyIDs), repo gains ListSchedulableByGroupIDAndPlatform/IsSchedulable filter and CindyCodexModelsAccountReaderMarker (L42-L64), upstream stub gains per-account bodies (L78, L85-L92), TestCodexModelsFailsOverWhenAPIKeyModelsEndpointIsUnavailable folded into TestCodexModelsFailsOverFromRetryableUpstreamStatus (L688-L713).", - "Helper wiring: performCodexModelsRequestForGroup defaults client_version to service.CindyCodexMinimumClientVersion (L910-L929) so non-Cindy tests are unaffected by the 426 gate.", - "Subject is the host handler plus service-level Cindy catalog projection observed end-to-end; the Cindy slug expectations (L191-L195) bind the test to the plugin catalog contents.", - "Not executed; the subprocess helper means these Cindy cases would spawn a child test process if run." - ] - }, - { - "path": "backend/internal/handler/openai_count_tokens_model_not_supported_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5c3dbb96f835d34cfeed9addfa0124d2d98de8fe7051d71daafc899d97ff8d10", - "review_fingerprint": "5c3dbb96f835d34cfeed9addfa0124d2d98de8fe7051d71daafc899d97ff8d10", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增的单测:writeCountTokensFailoverError 对 Reason=upstream_400_model_not_supported 的 failover 错误输出 Anthropic 信封的 400,error.type 与 error.code 均为 model_not_supported、message 为固定客户端文案。对应 openai_gateway_count_tokens.go L421-L446 的下游新增映射;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L14-L31 single test; decodes envelope and asserts status 400 plus type/code/message from service.OpenAIModelNotSupportedCode / OpenAIModelNotSupportedClientMessage.", - "Subject function is package-private in the same handler package; new downstream file (no upstream blob).", - "Not executed; static read only." - ] - }, - { - "path": "backend/internal/handler/openai_embeddings.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "79efdbaa7e8833e8179efc107af0537f7e7068e2f777ca67b243aebefa91ad10", - "review_fingerprint": "79efdbaa7e8833e8179efc107af0537f7e7068e2f777ca67b243aebefa91ad10", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "POST /v1/embeddings 宿主入口,无插件域业务。下游相对上游把 failover 循环对齐到其他 OpenAI 入口:同账号重试改为 openAIFailoverRetryState + ReacquireOpenAISameAccountSelection + acquireResponsesAccountSlotForSameAccountRetry,新增 ShouldRetryNextAccount 终止、OAuth 429 停止判断、finalizeOpenAIFailoverSelection/ReleaseOpenAIRuntimeBreakerProbeForSelection 探针收尾、trafficObserver,用量改为 snapshotOpenAIUsageMetadata 且经 shouldSubmitOpenAIUsage 门控。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L127-L340 loop: failedAccountIDs keyed by account.ID (L281); failoverClientGone at L150 and L246 (probe released); accountReleaseFunc + trafficTurn.Finish deferred in the forward closure (L220-L228); retryState.Handle Canceled on ctx.Done.", - "L311-L334: success path reports ForSelection then snapshots usage with apiKey/account identities captured before the async task; non-failover forward errors report failure (L301).", - "Minor ordering difference vs sibling handlers: L288 RecordOpenAIAccountSwitch is called before the ShouldStopOpenAIOAuth429Failover check (L289) so a switch is counted even when the loop then stops; metrics-only, not a correctness defect.", - "Diff vs aea725f: removed inline ReportOpenAIAccountScheduleResult/openAIAccountScheduleModel calls and pkg/ip import; no streaming path (stream=false). No test execution." - ] - }, - { - "path": "backend/internal/handler/openai_failover_retry.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d74cf375fad5ad92dea8d48c7923372d5bf1c9a94b666bdd40b793e21d74e726", - "review_fingerprint": "d74cf375fad5ad92dea8d48c7923372d5bf1c9a94b666bdd40b793e21d74e726", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增文件,抽出所有 OpenAI 入口共享的 failover 决策:openAIFailoverRetryState.Handle/HandleHTTP(同账号重试预算、ctx.Done 返回 Canceled、耗尽后 CooldownOpenAIRetryExhausted 再切号)、openAISameAccountRetryLimit(API key 仅按 pool_mode 配置状态码、OAuth 对 408/5xx/传输错误最多 1 次、401/403/429 立即切号、Cindy 余额不足恒为 0)、finalizeOpenAIFailoverSelection(同账号重试上报、失败上报或仅释放探针)、failoverAfterSameAccountSlotFailure(重获槽超时转为冷却+切号)、openAIResponseHasSemanticWrite(忽略 keepalive 字节)以及 clearCindyHTTPToWSV2StickyBeforeAccountSwitch(按 service 设置的 CindyHTTPToWSV2FirstTurn 标志清 sticky,本身是通用会话粘性机制)。属宿主调度/协议机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L143-L174 retry-limit policy; Cindy balance check delegates to failoverErr.CindyBalanceInsufficient (sanitized by service) or service.IsCindyBalanceInsufficientResponse rather than parsing budgets here.", - "L200-L259 Handle: select on ctx.Done vs time.After(retryDelay) returns openAIFailoverRetryCanceled so callers stop on client disconnect; L243-L246 nil-ctx fallback sleeps.", - "L263-L315 HandleHTTP only for service.IsOpenAIOfficialHTTPFailover accounts; returns Reselect (not exact-account) and intentionally skips the downstream cooldown breaker (comment L290-L291).", - "L22-L79 failoverAfterSameAccountSlotFailure refuses when client gone or response already has semantic bytes, cools the account, adds account.ID to failedAccountIDs and enforces maxAccountSwitches/OAuth-429 stop before allowing re-entry.", - "New downstream file; callers are the sibling handlers in this slice. No test execution." - ] - }, - { - "path": "backend/internal/handler/openai_failover_retry_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5b4d6e6fb630ae197bd437ddcef2048c903a4b5d4fc3aad50487b645526999b6", - "review_fingerprint": "5b4d6e6fb630ae197bd437ddcef2048c903a4b5d4fc3aad50487b645526999b6", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "openai_failover_retry.go 的下游新增单测,静态阅读未执行。断言证明:pool_mode API key 默认仅 401/403/429 使用配置的重试次数,408/5xx/传输错误与通用 400 为 0;非 pool_mode 为 0,显式 pool_mode_retry_status_codes 才放行 503;Cindy 账号的预算 429(原始 ExceededBudget body 或已消毒的 CindyBalanceInsufficient 标志)恒为 0 而普通 429 保留预算;OAuth 对 503/传输错误最多 1 次且 429 为 0;retryState 用完预算后调用一次 CooldownOpenAIRetryExhausted 并返回切号;openAIResponseHasSemanticWrite 忽略 compact SSE/images JSON keepalive 字节但识别真实写入。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L40-L66 table for openAISameAccountRetryLimit with a pool_mode account (retry count 10); L68-L83 pool-mode/explicit status prerequisites; L85-L121 Cindy budget cases; L123-L145 OAuth bounds.", - "L147-L176 state machine: SameAccount, SameAccount, then SwitchAccount with cooldown.calls==1 via openAIRetryCooldownRecorder (L15-L26).", - "L178-L203 uses real service.StartOpenAICompactSSEKeepalive / StartOpenAIImagesJSONKeepalive goroutines with require.Eventually and t.Cleanup(stop).", - "New downstream file; not executed." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_cindy_count_tokens_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8a92dc22dc37b091093a4d7ac8d4719edd28574b7d61d0014d3e931ba9b61ea0", - "review_fingerprint": "8a92dc22dc37b091093a4d7ac8d4719edd28574b7d61d0014d3e931ba9b61ea0", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/openai_gateway_cindy_image_validation_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "84541361fdd672eab51aae3fa17ea7d2e2e69fe81e492e9716771b66ff3d02c5", - "review_fingerprint": "84541361fdd672eab51aae3fa17ea7d2e2e69fe81e492e9716771b66ff3d02c5", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/openai_gateway_count_tokens.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e8b6712b1ea94fabc48b91055fbdd8efa2767d22f9927a9374650bbd5739dc88", - "review_fingerprint": "e8b6712b1ea94fabc48b91055fbdd8efa2767d22f9927a9374650bbd5739dc88", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "三个不计费的 token 计数入口:ResponsesInputTokens(/v1/responses/input_tokens)、GrokCountTokens(本地估算)、CountTokens(Anthropic 兼容 count_tokens 经 OpenAI 桥接)。下游相对上游:ResponsesInputTokens 与 CountTokens 从 SelectAccountForTokenCount 改为 SelectAccountWithSchedulerForCapability(前者 defer ReleaseFunc,后者带完整 failover 循环、静默取槽后由本处理器用 Anthropic 信封渲染 429);CountTokens 新增 Cindy 身份分组直接 404(ClassifyCindyIdentityGroup 桥接判定,不复刻规则)与 WithOpenAICindyRequestedModel 上下文;新增 writeCountTokensFailoverError 把 5xx 透传状态、其余 502,并将 model_not_supported 映射为结构化 400。发现一处低危:ResponsesInputTokens 对带探针的 selection 不上报也不释放探针(见 findings)。属宿主协议机制;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L95-L96 and L284-L288: profit gate suppressed for token counting (WithOpenAIProfitControlSuppressed) as in upstream; L208-L216 new Cindy identity rejection before dispatch permission.", - "L309-L419 CountTokens loop: c.Request.Context().Err() short-circuit (L326), failedAccountIDs keyed by account.ID (L407), accountRelease deferred in attempt closure (L373-L378), finalizeOpenAIFailoverSelection on every failover branch, success reported ForSelection (L380).", - "Finding recorded: ResponsesInputTokens (L100-L140) neither reports a schedule result nor releases a runtime breaker probe for its selection (only selection.ReleaseFunc).", - "Diff vs aea725f: +errors import, +writeCountTokensFailoverError (L421-L446), comment updated to 'without taking concurrency slots'. No test execution." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_credential_failover_loop_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b772feb4271adfe9237b221e257f0bf22569c5503d11cb44a4111f7ecc7d9207", - "review_fingerprint": "b772feb4271adfe9237b221e257f0bf22569c5503d11cb44a4111f7ecc7d9207", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "//go:build unit 的 Grok OAuth 凭据 failover 集成式单测(真实 OpenAIGatewayService + 内存 repo/upstream/refresher stub,经 gin 路由调用 Responses/ResponsesWebSocket/Messages/ChatCompletions/GrokVideo*)。断言证明:刷新被撤销的账号被 SetError 后选择健康账号且只打健康账号;供应商配置错误、父上下文取消、映射后取消、状态写入失败、缺失 provider 时都在重选前停止且不惩罚账号;预取消请求不调用选号器;429 切换有界、402 冷却排除、混合状态(429→OAuth 500 现返回 503)、OAuth 429 后 API key 失败不能突破上限;Grok 媒体传输错误在同一账号精确重试至多一次再切号,401/403/429 立即切号,视频查询不重放。Grok 是核心平台而非七个插件域,属宿主调度机制的正确性测试。下游相对上游新增 sticky 会话 gatewayCache stub、transportOnce/transportFailures、四个媒体传输测试与 wireOpenAIWSFixtureGroupReader。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f: +grokCredentialHandlerGatewayCache (L42-L109) implementing session/reasoning/grok-video cache methods, +transport failure injection (L389-L420), 'mixed_429_500' expectation changed 502->503 (L717), +TestGrokMediaTransientTransportRetriesExactSameAccount / ...AtMostOnceBeforeSwitching / ...AuthenticationAndRateLimitFailuresSwitchImmediately / TestGrokVideoLookupTransientTransportDoesNotReplayOrSwitch (L780-L848), fixture wiring L1081 and L1097.", - "Account identity assertions: repo.errorIDs()/setTempIDs/rateLimitedAccountIDs and upstream.accountHits() are compared against exact account IDs 801/802/803 in every case.", - "Cancellation assertions: L527-L575 and L969-L984 use refresher.started channel and repo.selectorCalls()==1 to prove no reselection after cancel; L577-L605 pre-cancelled requests never call the selector for four endpoints.", - "Not executed; requires the unit build tag." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_first_output_timeout_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f633e87926a7c61bbd0aa586d0bd537db26bd8bbcfa7f35867c48902dfbb8874", - "review_fingerprint": "f633e87926a7c61bbd0aa586d0bd537db26bd8bbcfa7f35867c48902dfbb8874", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "首字输出超时 failover 辅助函数的单测。上游已有:仅在非语义写入(keepalive ':' 注释)后且 SafeToFailoverAfterWrite 时允许切换、首字 failover 只允许一次切号、客户端取消后不允许重放。下游新增 TestOpenAIFirstOutputFailoverDoesNotCapRefusalRecoveryAccountSwitches:NewOpenAICyberFailoverError(拒答恢复)产生的错误不计入首字切号上限(count 保持 0)。被测函数属宿主网关 failover 机制;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f adds only L40-L48; other three tests unchanged.", - "Subjects: openAIForwardMayFailover, openAIFirstOutputFailoverExhausted, openAIRequestAllowsFailoverReplay (all in openai_gateway_handler.go).", - "Not executed; static read only." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "8023be802264a806d2233ee667d66ade5d966606cfb03d3e6f4d6cdec39917f5", - "review_fingerprint": "8023be802264a806d2233ee667d66ade5d966606cfb03d3e6f4d6cdec39917f5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 网关核心(约 5583 行):Responses/Messages HTTP 入口、Responses WebSocket v2 ingress、并发槽获取与利润终检三态、codex automation/delegation bootstrap 归一化与心跳/委托 XML 严格校验、handleFailoverExhausted 的完整错误归类(请求被拒、体过大、model_not_supported、continuation_state_unavailable、alpha-search 桥、拒答/cyber 恢复、凭据、Cindy 余额、透传规则、默认映射)、用量深拷贝快照、cyber 会话屏蔽与风控记录、WS 关闭码映射。下游 vs aea725f(+1872/-620):Cindy 身份分组与续链分类(opaque binding/legacy Laxa 会话粘连走专用调度入口)、严格 Cindy 模型与图桥门(均经 service 扩展桥接,无第二执行者)、compact v2 与 SSE 心跳、同账号重试状态机 + 官方 HTTP failover、首字超时上限次序、跨透传 reasoning 消毒接缝、WS per-turn 定价/利润复核/槽位重取/流量观测/逐 turn 模型白名单、探针化调度上报(ForSelection)取代 openAIAccountScheduleModel;同时移除了 handler 级 previous_response_id 按用户所有权校验(记为 medium finding)。已按 63a98c8cc 后当前字节复审:图桥路由模型改由 CindyResponsesImageRoutingModel(ctx) 解析(不再钉 CindyDefaultTestModel),WS per-turn provider 定价改为 NewProviderPricingTurnContexts 的 Copy(BeforeTurn)/Take(AfterTurn) 快照,未捕获定价上下文的 turn 拒绝提交用量。复审于 6258adab5(HEAD 49c1e8d83)并确认属主校验已恢复:Responses 在锚点语法校验后、任何调度/IO 之前按中间件身份(subject.UserID + apiKey.ID,按 apiKey.GroupID 分组作用域)校验 previous_response_id 属主,未知/跨组/存储失败一律 400 且不泄露错误文案,随后为每个通过请求登记属主上下文并由既有 bindHTTPResponseAccount 链在三条 HTTP 转发路径上持久化;ValidateOpenAIHTTPResponseOwner/SetOpenAIHTTPResponseOwner 恢复生产调用者;图桥路由与 WS 逐 turn 定价区域未变(仅行号 +23)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Read extent: full sequential read (10 chunks to EOF) of the pre-63a98c8cc bytes (63a98c8cc~1 blob sha e94e08200f29... matches), plus git diff 63a98c8cc~1..05e25bdf2 covering the two regions changed there (Responses image routing; WS turnProviderPricing), plus git diff 05e25bdf2..HEAD(49c1e8d83) which is exactly +23 lines (commit 6258adab5, Responses L589-L610) read in full context L576-L640; current sha self-computed 8023be802264....", - "Cancellation/cleanup anchors: openAIRequestAllowsFailoverReplay at loop head (L892), failoverClientGone branches release the breaker probe without penalizing the account (L1146-L1152), WS defer releaseTurnSlots + finishOpenWSTrafficTurn safety net (L3081-L3100), openAIWSIngressEndedByClient stops client disconnects from counting as account failures (L197-L209 with rationale comment), ingress lease released via defer (L2823-L2827).", - "Identity/boundary anchors: usage snapshot deep-copies apiKey/user/account/subscription before async tasks (L3993-L4141); Cindy/strict checks delegate (ClassifyCindyIdentityGroup, CindyModelSupportsEndpoint, ResolveCindyResponsesImageToolsForAccount, ClassifyCindyContinuation, LookupCindyOpaqueContinuationBinding); legacyLaxaContinuationCanSwitchAccount and continuation binds prevent replaying credential-bound state onto sibling accounts (L1193-L1236, L3162-L3200).", - "Finding (medium) resolved by 6258adab5: L589-L607 validates previous_response_id ownership via h.gatewayService.ValidateOpenAIHTTPResponseOwner(groupID from apiKey.GroupID, subject.UserID, apiKey.ID) immediately after the anchor syntax check and before ensureCompositeTargetPlatform, Cindy classification/continuation store lookups, channel mapping, slots, billing and scheduling; store error or unknown/foreign owner -> 400 'previous_response_id is not available for this user' (L602-L605, error text not echoed); L610 SetOpenAIHTTPResponseOwner(c, subject.UserID, apiKey.ID) stamps every request that passes the gate. Bind chain: service/openai_gateway_response_handling.go bindHTTPResponseAccount L1672-L1674 reads the same context key and is invoked from openai_gateway_forward.go L1517 (Forward JSON+SSE), L1131 (Cindy HTTP->WSv2 bridge) and openai_gateway_passthrough.go L682, with context.WithoutCancel + bounded timeout. rg (non-test): Validate has caller L596, Set L610, Bind L1674. Structure matches upstream aea725f L496-L531 (downstream anchor check is stricter). Not re-established for WS first frames (same as upstream). Minor: the lookup-failure warn drops zap.Error vs upstream (diagnostics only).", - "codex bootstrap normalizers (L2067-L2500) are host protocol mechanisms that predate v0.2.7 upstream (aea725f L1644+); rg finds no duplicate in plugins/codex-runtime. No test execution." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "78362ed83bddecd1a6e21147bc752f0813dbb8b4aaf7f655a732afa248ec1389", - "review_fingerprint": "78362ed83bddecd1a6e21147bc752f0813dbb8b4aaf7f655a732afa248ec1389", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/openai_gateway_native_usage_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b0feee1dfbc5efb1106f8281f39cc858d0ee7b01705dbc9221cdfb7b901ffdda", - "review_fingerprint": "b0feee1dfbc5efb1106f8281f39cc858d0ee7b01705dbc9221cdfb7b901ffdda", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增单测(30 行):openAIForwardResultFromNativeAnthropic 把原生 Anthropic ForwardResult 转成 OpenAIForwardResult 时保留计费语义——UsageInputTokensExcludeCache=true、五类缓存 token 逐字段搬运、BillingModel 取 UpstreamModel、UpstreamEndpoint 固定 /v1/messages。该转换是混合分组选中 Cindy 账号时 Messages 原生直通路径的计费桥(openai_gateway_handler.go L72-L100),属宿主计费机制的正确性测试。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L10-L30 single test asserting InputTokens=100 excl-cache flag, CacheCreation 10/5m 4/1h 6, CacheRead 20, BillingModel anthropic/claude-opus-5.", - "Subject openAIForwardResultFromNativeAnthropic defined in openai_gateway_handler.go L72-L100; new downstream file.", - "Not executed; static read only." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_reasoning_failover.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "13292e9f764e3313c192c7a0f1649331a498172c5f177dc63d1c9e1b2208676c", - "review_fingerprint": "13292e9f764e3313c192c7a0f1649331a498172c5f177dc63d1c9e1b2208676c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "跨透传边界 failover 的请求体派生(65 行):一旦本请求尝试过 openai_passthrough 账号(Kiro),后续非透传账号(Bedrock 等)的 attempt body 从不可变 canonical body 剔除上游私有加密 reasoning item(SanitizeOpenAICrossModeFailoverReasoning),且该消毒跨重试/后续账号保持粘性;透传前与透传族内保持原体。下游相对上游仅新增一处:IsCindyRuntimeCompatibleAPIKeyAccount(legacy Laxa)账号直接返回 canonical body 且不置 passthroughSeen——Cindy 兼容账号不是 OpenAI 透传尝试。判定委托 service,无插件规则复刻;属宿主 failover 机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f: only L32-L34 added (Cindy runtime-compat early return).", - "L26-L64 deriveOpenAIForwardAttemptBody: invoked exactly once per forward attempt (comment L24-L25), sanitize errors fall back to canonical body with a warn, canonical slice never mutated.", - "Caller: openai_gateway_handler.go Responses loop L1046 (attemptBody per attempt).", - "Not executed; static review only." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_reasoning_failover_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7424e3e63e830dc36041c5a8cb0cc07803929318447f9f897e2876854647af20", - "review_fingerprint": "7424e3e63e830dc36041c5a8cb0cc07803929318447f9f897e2876854647af20", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "deriveOpenAIForwardAttemptBody 的单测:Kiro→Bedrock 跨模式切号剔除整个加密 reasoning item(含耦合 id/summary,消息项保留,canonical 不变);非透传→非透传、透传族内、非透传→透传、同账号重试均保留 reasoning;消毒在后续 Bedrock 重试与更换账号间保持粘性。下游新增 TestLegacyCindyRuntimeCompatibilityPreservesReasoningAcrossFailover:laxarouter 凭据的 legacy Cindy 账号保留 reasoning 且不置 passthroughSeen,legacy→普通账号切换仍保持 canonical。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f adds only L148-L171 (legacy Cindy case); earlier four tests unchanged.", - "L49-L80 cross-mode strip asserts reasoningItemCount 1→0, no encrypted_content/rs_kiro_abc123/ENC_BLOB remains, surviving messages intact, canonical JSONEq preserved.", - "L127-L146 stickiness across bedrockA retry and bedrockB switch.", - "Not executed; static read only." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_usage_context_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "045663c30753b97e03438e2ed6daebdbc10ec5c950b2a034748fb210738858ed", - "review_fingerprint": "045663c30753b97e03438e2ed6daebdbc10ec5c950b2a034748fb210738858ed", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "用量记录上下文与快照所有权测试。上游已有两例:GatewayHandler/OpenAIGatewayHandler 的 submitUsageRecordTask 把 ClientRequestID/RequestID 复制进任务 ctx。下游新增:TestSnapshotOpenAIUsageMetadataOwnsValuesBeforeAsyncDispatch 证明 snapshotOpenAIUsageMetadata 先深拷贝再异步——事后改写 apiKey.ID/groupID/account.ID/RateMultiplier/ParentAccountID/订阅窗口/credentials/UA 均不影响已生成的 usageInput(含 ChannelID 与映射模型);TestShouldSubmitOpenAIUsageRequiresSuccessfulResult 证明仅 err==nil 且 result!=nil 才提交(context.Canceled 或 nil result 不提交)。防止异步计费读到被复用的 gin 上下文/可变对象,属宿主计费机制正确性。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f adds L47-L92 (two tests); the two ctx-copy tests unchanged.", - "L64-L84: mutations after snapshot (including account.Credentials['api_key']='changed' and header rewrite) do not leak into snapshot.Input; asserts original values 7/10/snapshot-agent/11/gpt-5.6-sol/secret/6/1.25/4/unix20.", - "Subjects: snapshotOpenAIUsageMetadata & shouldSubmitOpenAIUsage in openai_gateway_handler.go L4011-L4251.", - "Not executed; static read only." - ] - }, - { - "path": "backend/internal/handler/openai_gateway_ws_model_allowlist_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fbd83100b31e3e6f72a7aaa35538cf1b74e8b54f800690814ee9fc2c12aad737", - "review_fingerprint": "fbd83100b31e3e6f72a7aaa35538cf1b74e8b54f800690814ee9fc2c12aad737", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/openai_http_response_owner_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "34aa42a620bfa99be7447f8345219120457deafea4006d17d88f8e979dd2234d", - "review_fingerprint": "34aa42a620bfa99be7447f8345219120457deafea4006d17d88f8e979dd2234d", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "全文复核198行内存fixture:真实HTTP handler/Forward/passthrough建立响应后阻止另一个同组用户续链,允许同用户换key并登记后续响应;body身份无权、unknown/group/cache错误均在fake IO前关闭。repo/cipher/response均合成且billing cache收尾;未验证真实数据泄露或持久Redis。", - "evidence": [ - "artifacts/evidence/v027-astra-http-response-owner-review.json", - "Parent read the entire fixture and matched current SHA; only the report-specific targeted commands were run." - ] - }, - { - "path": "backend/internal/handler/openai_images.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a2b908b2616c99a48d8bd68320dfc1029329367d0deab81e8c8e708aeb655ee0", - "review_fingerprint": "a2b908b2616c99a48d8bd68320dfc1029329367d0deab81e8c8e708aeb655ee0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "POST /v1/images/generations|edits 宿主入口:解析(含 multipart)、生图权限与并发槽、审计、渠道映射、调度循环、JSON keepalive、强制用量落库(submitMandatoryUsageRecordTask)。下游相对上游新增:严格 Cindy 分组的端点级模型门与请求参数校验(CindyModelSupportsEndpoint + ValidateCindyImageRequestForAccount,选号前按分组、选中 Cindy 账号后再按账号复验;imagePolicyError 把 ErrExtensionOperationDisabled/Unavailable 映射 503,证明规则来自扩展桥接而非本地复刻,image-tools 域无第二执行者)、非严格分组要求 IsNativeOpenAIImagesModel 或目录图模型、SelectAccountWithSchedulerForImages 增加 cindyEndpoint 与 requestPlatform、同账号重试改 retryState + Reacquire、ForSelection 上报、trafficObserver、shouldSubmitOpenAIUsage 门控与快照化用量。发现一处低危:ImageCount>0 的部分错误提前 return 未收尾探针/上报(见 findings)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L95-L117 strict-Cindy gating delegates to service (extension-bridged: imagePolicyError L20-L26 maps ErrExtensionOperationDisabled/Unavailable to 503); L272-L287 re-validates for the actually selected Cindy account and releases the selection on rejection.", - "L193-L456 loop: failoverClientGone releases probe (L383-L390), keepalive-adjusted writer size guards flush-after-write failover (L325, L374), accountReleaseFunc + trafficTurn.Finish deferred in forward closure (L327-L335), retryState.Handle Canceled on ctx.Done, OpenAIImagesUpstreamError user-errors do not penalize the account (L355-L370, !retryableServerError reported as success).", - "L458-L492: mandatory usage task with identities captured pre-async; multipart payload hash uses StickySessionSeed.", - "Finding recorded: L346-L353 partial image-error early return (downstream added the return) skips selection finalization.", - "Diff vs aea725f also removes pkg/ip and openAIAccountScheduleModel usage. No test execution." - ] - }, - { - "path": "backend/internal/handler/openai_images_failover_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7ad9e56b66c73d9cb3e1b66439dfb5bb226bb1a407f85a85dc9774b174f7f61e", - "review_fingerprint": "7ad9e56b66c73d9cb3e1b66439dfb5bb226bb1a407f85a85dc9774b174f7f61e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "//go:build unit 的 Images failover 测试。上游已有流内 server_error 跨账号切换一例,下游把期望从 [1,2] 改为 [1,1,2,2](OAuth 传输/5xx 每账号先同账号重试一次,佐证 retryState 语义)并把 ops failover 事件数 2→4;日志断言 img_quality/img_size 记录而 prompt 不落日志。下游新增两例 Cindy 预算拒绝:严格 Cindy 分组请求免费池图模型且账号预算耗尽时在选号前即返回 404 model_not_found(上游零调用、零余额探测、零 MarkCindyBalanceInsufficient、不泄露 budget_exceeded/敏感文案);legacy(PlatformOpenAI+laxarouter 凭据)分组同样选号前 404 且不触上游。被测为宿主 Images 调度/脱敏与 service 级 Cindy 预算信号(消毒后进 handler),静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f: +time import, +ListByGroup on repo stub, +cindyNativeImagesBudgetRepo/Upstream + HTTP201 upstream (L73-L172), expectation [1,2]->[1,1,2,2] and events 2->4 (L297-L310), +two Cindy tests (L313-L433).", - "L368-L374: require.Empty(imageCalls/probeCalls/marked) plus NotContains 'budget_exceeded'/'sensitive upstream budget detail' prove pre-selection rejection without probes or leakage.", - "L287-L295 asserts img_quality/img_size logged and prompt absent from the account_selecting log fields.", - "Not executed; requires the unit build tag." - ] - }, - { - "path": "backend/internal/handler/openai_legacy_cindy_continuation.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "e08a3b0fbc425ed1fa06619d08ae7c8c80ad3a7f258a388bc8364ce13037ac21", - "review_fingerprint": "e08a3b0fbc425ed1fa06619d08ae7c8c80ad3a7f258a388bc8364ce13037ac21", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/openai_legacy_cindy_continuation_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c49fa6604bda67e2b76e8df01ef607fe3227183d45c1601ac0eb49b472a028fa", - "review_fingerprint": "c49fa6604bda67e2b76e8df01ef607fe3227183d45c1601ac0eb49b472a028fa", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/openai_management_isolation_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7f4bcea95eacc06da7a3042f9da8b2fd612ce774cbc34b3e79f6793227e7b932", - "review_fingerprint": "7f4bcea95eacc06da7a3042f9da8b2fd612ce774cbc34b3e79f6793227e7b932", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增(上游无此文件)的管理面隔离测试:32 个并发 /openai/v1/responses 请求全部阻塞在慢上游(timeout/502/503/429/流内错误五种结局)期间,sqlmock 支撑的账号 repo 证明网关请求在等待上游前已释放数据库连接(db.Stats().InUse==0、连接池 ≤4),/health 与三个 admin 账号管理路由在 1s 超时内正常 200;释放上游后全部请求收尾、无阻塞泄漏(blocked==0),重试与切号总调用 ≤3×请求数。证明网关平面阻塞不串行化管理平面 DB 访问,属宿主资源隔离正确性。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "L27-L100 managementIsolationUpstream blocks on a release channel and honors req.Context().Done; L102-L135 databaseBackedIsolationAccountRepo probes SELECT 1 per selection so DB usage during scheduling is observable.", - "L265-L274: after all 32 requests are inside the upstream, require InUse==0 and OpenConnections<=4; L276-L290 management routes answer within a 1s context while upstreams stay blocked.", - "L292-L315: after release, all requests finish within 15s, upstream.blocked==0, every outcome kind occurred, total upstream calls <= 3x requests (bounded retries).", - "New downstream file (no upstream blob), no build tag; not executed." - ] - }, - { - "path": "backend/internal/handler/openai_models_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9e667cebb9cbaa17b2ae41e23801f9eeda63ea42c50e3359f9dc14d672be626a", - "review_fingerprint": "9e667cebb9cbaa17b2ae41e23801f9eeda63ea42c50e3359f9dc14d672be626a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "GatewayHandler 的固定账号 OpenAI 模型发现:pinnedOpenAIModels 经 FetchPinnedOpenAIModelsList 拉取(单模型路径清空集合 ETag),writeOpenAIModelsResponse 处理 ETag/304 与 /models/{model} 单模型检索(writeRetrievedModel 逐条解包,未命中返回 model_not_found 信封)。下游相对上游仅删除 writeModelsListResponse 辅助函数(16 行)——rg 全库无调用者,属迁移后死代码清理,无行为变化;容量投影与目录规则在 service/插件侧,此处纯宿主发现机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S01-handler-openai-1-review.json", - "Diff vs aea725f: only removal of writeModelsListResponse (upstream L64-L79); rg --no-config 'writeModelsListResponse' over backend returns nothing, confirming dead-code deletion.", - "L14-L42 pinnedOpenAIModels: context-cancellation checks before and after fetch, ErrNoPinnedCodexModelsAccounts mapped to 503, ops selected account recorded for the successful pinned account.", - "L22-L25 single-model requests clear If-None-Match because a collection ETag cannot validate a single-model body.", - "No test execution; static review only." - ] - }, - { - "path": "backend/internal/handler/openai_models_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b6c432313587736dbbd039a2755f2ec08b3a5837ec6e1d1bd13432a1373cd1b5", - "review_fingerprint": "b6c432313587736dbbd039a2755f2ec08b3a5837ec6e1d1bd13432a1373cd1b5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "网关 /v1/models 与 /models 钉选模型清单测试,上游 aea725f 已有本文件。下游差异(+96/-3):构造 GatewayHandler 时断言并注入 nativeAnthropicGatewayService(L18-L19);新增 requirePinnedModelContextCapacity(L37-L60)断言 wire 上的 context_window/max_context_window/context_capacity_source;新增 TestPinnedModelsFinalETagTracksLocalCapacityWithoutRefetching(L102-L154)证明 ETag 随账号本地容量覆盖(ModelContextOverridesExtraKey)变化、304 命中且不重取上游原始缓存;wildcard/mapping 两用例改用容量断言并区分 relay 宿主 upstream 声明优先于 official 目录。被测主体是宿主网关模型清单协议(账号选择、ETag、允许列表、容量投影出口),容量目录数据本体在 model-policy 插件目录,此处只验证核心协议出口。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "git diff aea725f..worktree: new helper requirePinnedModelContextCapacity, new test TestPinnedModelsFinalETagTracksLocalCapacityWithoutRefetching, capacity assertions replacing raw context_window:424242 Contains checks in TestPinnedModelsAllowlistExpandsWildcards/TestPinnedModelsMappingFollowsUpstreamDiscovery", - "Call chain: helpers newPinnedCodexTestHandler/codexModelsPinnedHTTPUpstream/performPinnedCodexModelsRequest defined in backend/internal/handler/openai_codex_models_handler_test.go L931-L1042; resolver service.ResolveAccountModelContextCapacity / NewAccountModelContextCapacityResolver in backend/internal/service/model_context_capacity.go; official catalog data lives in plugins/model-policy/catalog/catalog_data.go", - "Test read statically only; no test execution, no production behavior claimed." - ] - }, - { - "path": "backend/internal/handler/openai_official_http_failover.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c50374c960bd3f07d111ffef81da542c5efc33b7a1450a976566d70f465391c4", - "review_fingerprint": "c50374c960bd3f07d111ffef81da542c5efc33b7a1450a976566d70f465391c4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增源文件:OpenAI 官方 HTTP 账号的调度结果上报与 failover 终结分流。isOpenAIOfficialHTTPFailover 命中时走 ReportOpenAIOfficialHTTPAccountScheduleResult,上报模型按 result.UpstreamModel > ops 上下文 OpsUpstreamModelKey > ResolveOpenAIAccountUpstreamModelForRequest 的优先级取实际上游模型(L16-L30),失败但客户端已断开时跳过上报(L43-L45)避免误惩罚账号;非官方账号保留下游 selection 上报与 finalizeOpenAIFailoverSelection(注释明确含 Cindy/OAuth/托管路由,L60-L74)。属宿主转发调度机制而非单一插件业务规则。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f prints nothing for this path -- new downstream, whole file is the delta.", - "Call chain: invoked from backend/internal/handler/openai_chat_completions.go L368-L449 and backend/internal/handler/openai_gateway_handler.go L1155-L1308; service side IsOpenAIOfficialHTTPFailover / ReportOpenAIOfficialHTTPAccountScheduleResult / ResolveOpenAIAccountUpstreamModelForRequest in backend/internal/service/openai_official_http_failover.go L20-L41; failoverClientGone in backend/internal/handler/failover_loop.go L332; finalizeOpenAIFailoverSelection in backend/internal/handler/openai_failover_retry.go L176.", - "No duplicated executor: official path reports before retry decisions (as upstream), downstream finalizer stays exclusive to non-official accounts; no defect found in the branch logic." - ] - }, - { - "path": "backend/internal/handler/openai_official_http_failover_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6a2279bd8a7910c85656e332597174e9dc2e2fd4f324850b2de1c256e2decd1a", - "review_fingerprint": "6a2279bd8a7910c85656e332597174e9dc2e2fd4f324850b2de1c256e2decd1a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "官方 HTTP failover 组合测试(//go:build unit,下游新文件):真实 handler、重试策略、选择器、转发与限流服务运行,仅上游 IO 与持久化为内存桩(复用 grokCredentialHandlerRepo/Cache)。断言:503 后经普通选择器重选可用账号且请求体逐字节不变、会话粘性保持(assertStableSession);pool_mode_retry_count 预算(默认 3、显式 0)跨重选按账号保留;native Responses 识别特定瞬态 400 文案在同账号重试而 passthrough 路由保持不同谓词;H2 传输错误每账号只试一次且不写入临时冷却;客户端取消停止重选并以 statusClientClosedRequest 静默收尾;已产生语义输出(SSE delta)后禁止重放、缺失终止不得改写为成功且保留显式 error。证明的是核心调度/转发机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream test, whole file is the delta.", - "Concrete anchors: TestOpenAIOfficialHTTPRetryReselectsAvailableAccount L220-L253 (accounts 45111->45112, JSONEq on both attempt bodies, selectorCalls>=2), TestOpenAIOfficialHTTPRetryBudgetSurvivesReselection L255-L285, TestOpenAIOfficialHTTPNativeResponsesTransientProcessingRetries L287-L308, TestOpenAIOfficialHTTPTransportFailureDoesNotReplaySameAccount L310-L343 (setTempIDs/errorIDs empty), TestOpenAIOfficialHTTPClientCancellationStopsReselection L345-L366, TestOpenAIOfficialHTTPSemanticOutputStopsReselection L368-L393.", - "Call chain: fixtures grokCredentialHandlerRepo/grokCredentialHandlerGatewayCache reused from existing handler failover tests; newReplayableEndpointContext from openai_replayable_endpoints_failover_test.go; real service.NewOpenAIGatewayService wiring at L210-L217.", - "Statically read only; test not executed, no behavior verified at runtime." - ] - }, - { - "path": "backend/internal/handler/openai_official_http_retry_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8a66de8ce88857382e2d2d428a8979ffdde6ee2b358d4156f7df4231f7ce92b0", - "review_fingerprint": "8a66de8ce88857382e2d2d428a8979ffdde6ee2b358d4156f7df4231f7ce92b0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "官方 HTTP 重试状态机单测(下游新文件)。TestOpenAIOfficialHTTPRetryPolicy(L24-L91)证明:默认 3 次同账号 reselect 后切账号、pool_mode_retry_count=0 禁用、容量信号与已分类瞬态 400 保留官方预算、普通 503 与 H2 传输失败不获得隐式重试、SameAccountRetryMax 与过期 deadline 优先,且官方重试不装下游冷却(cooldown.calls==0)。TestOpenAIOfficialHTTPRetryScopeIsolation(L111-L142)证明只有被 WithOpenAIOfficialHTTPFailover 标记的普通 API key 走 reselect:OAuth 切账号、Cindy 平台与旧 Laxa base_url 保持 exact 同账号、旧 Handle 入口不受标记影响——官方策略不越界改变 cindy-provider 等既有路径。另验证 openAIAccountScheduleModel 的取值优先级与 trim(L155-L166)及取消路径返回 openAIFailoverRetryCanceled(L144-L153)。主体为核心 openai_failover_retry.go 与 openai_official_http_failover.go。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream test.", - "Call chain: newOpenAIFailoverRetryState/HandleHTTP/Handle and openAIFailoverRetryAction in backend/internal/handler/openai_failover_retry.go (action type L115, finalize L176); service.WithOpenAIOfficialHTTPFailover in backend/internal/service/openai_official_http_failover.go.", - "Boundary proven: Cindy/Laxa/OAuth branches assert the official HTTP policy does not change other account families' retry semantics.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/handler/openai_profit_slot_recheck_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "50552bd509f5450167fbd83410e398559a7d3bbdc77001c0c6dff6626e2d8d19", - "review_fingerprint": "50552bd509f5450167fbd83410e398559a7d3bbdc77001c0c6dff6626e2d8d19", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/openai_profit_veto_budget_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": false, - "content_sha256": null, - "deleted_upstream_blob": "60e487112181e30f7d3b77c369216b8ce972dc64", - "review_fingerprint": "f1db0ff96bdec53acef4b98cd88c9927a8a485cca5b59b8c3c46fb1819e48892", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "验证最多10次排除、在500轮候选循环前停止,以及与FailoverState使用同一cap。 仅在runtime确实dormant的条件下按有意退休闭合;本轮两项回归验证不能重启门,不等价于旧helper循环测试。", - "evidence": [ - "Exact deleted blob and replacement assertion mapping: artifacts/evidence/v027-astra-deleted-path-review.json", - "该已删文件及旧profit-preview均未运行;独立dormant证据记录限定服务回归。", - "Deletion basis: 5f216d1d07f091b8942aa70e3c5ee3d7fc4153fe", - "The bound dormant implementation is included with this review; its exact eight source SHA256 values were verified before import." - ] - }, - { - "path": "backend/internal/handler/openai_reasoning_recovery_terminal_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4f9526f8d874ddc6ec5de6499d4b39c39c4a80c977dee06120ec7baf1f21ff0c", - "review_fingerprint": "4f9526f8d874ddc6ec5de6499d4b39c39c4a80c977dee06120ec7baf1f21ff0c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Responses 加密推理内容失败恢复的终局语义测试(//go:build unit,下游新文件)。证明:invalid_encrypted_content 触发恰好一次剥离 encrypted_content 的同账号重试(第二次请求 input.0.encrypted_content 不存在、其余 input 原样,L129-L133),终局失败不再进调度器、不换第二账号(accountIDs==[1,1]);已向客户端转发语义输出时禁止任何重放且 response.failed 只出现一次(L74-L77);上游 do-not-leak 文案不外泄;ops 错误日志同时记录客户端状态(400/502)与上游原始状态码(L140-L144);handleReasoningRecoveryTerminal 对 request_rejected 不上报账号健康失败、仅释放探针(L148-L159,native 与 passthrough 两态)。主体 handleReasoningRecoveryTerminal 位于核心 openai_gateway_handler.go L4334。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream test.", - "Call chain: handler.handleReasoningRecoveryTerminal in backend/internal/handler/openai_gateway_handler.go L4334; service.OpenAIReasoningRecoveryTerminalError / NewOpenAIRequestRejectedError in backend/internal/service; fixtures newOpenAIResponsesFailoverTestHandler (openai_responses_failover_cancel_test.go L212), cindyFailoverSelectionReporter (openai_cindy_http_wsv2_sticky_test.go L198), setupOpsErrorLogTestQueue (ops_error_logger_test.go L251).", - "Statically read only; not executed; no claim about runtime scheduler metrics beyond what assertions encode." - ] - }, - { - "path": "backend/internal/handler/openai_refusal_recovery_handler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2e0230ef72f6e516312f2f934cfaa8e06f235a171a6599f19004959cacfb2862", - "review_fingerprint": "2e0230ef72f6e516312f2f934cfaa8e06f235a171a6599f19004959cacfb2862", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "拒答恢复/cyber failover 耗尽的响应形态测试(下游新文件)。证明:handleFailoverExhausted 对 cyber 错误输出 503+Retry-After:1、code=upstream_retry_exhausted、retryable:true 且不泄漏内部 cyber_policy 代码(L15-L27);SSE 已开始时改为单个 response.failed 事件(L29-L42);Anthropic /v1/messages 变体输出 type=api_error 包体(L44-L55);recordOpenAIResponsesCyberAttempt 每次尝试后清空 ops cyber 标记与 cyberPolicyRecordedKey(L57-L71);prepareOpenAIRefusalPromptRetry 仅对拒答恢复错误注入一次 developer 前缀消息且幂等(L73-L93),普通 failover(nil)与 cyber 错误不改写请求体(L95-L117)。主体均在核心 openai_gateway_handler.go(handleFailoverExhausted L4351、prepareOpenAIRefusalPromptRetry L4888、recordOpenAIResponsesCyberAttempt L5540、cyberPolicyRecordedKey L5156)。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream test.", - "Call chain: service.NewOpenAICyberFailoverError / NewOpenAIRefusalRecoveryFailoverError / MarkOpsCyberPolicy / GetOpsCyberPolicy in backend/internal/service; handleAnthropicFailoverExhausted in openai_gateway_handler.go L1992.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/handler/openai_replayable_endpoints_failover_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a88f9b8da6571f2dc59c4f2574a72c5713cbec2698ba9e1ba1dec6ea01d0b72d", - "review_fingerprint": "a88f9b8da6571f2dc59c4f2574a72c5713cbec2698ba9e1ba1dec6ea01d0b72d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "可重放非会话端点的 failover 语义测试(//go:build unit,下游新文件),覆盖 /v1/alpha/search、/v1/embeddings、/v1/images/generations、/v1/messages/count_tokens。证明:pool_mode 配置的 503 在 exact 同账号重试(calls [1,1],L215-L224/L246-L255/L307-L317);Images 传输错误切换账号且同账号不隐式重放,两次传输错误后向客户端返回 502(L257-L286);401/403/429 切换账号(L288-L305);开启旧 alpha-search 桥接设置时普通 API key 不切换端点、上游 400 原样透传且 GetUpstreamEndpoint 标记 EndpointAlphaSearch(L226-L244)。构造真实 OpenAIGatewayService+SettingService(L134-L192)。被测的是宿主转发/调度,Images 端点在此仅作为网关转发目标,不涉及 image-tools 插件业务规则。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream test.", - "Call chain: h.AlphaSearch/h.Embeddings/h.Images/h.CountTokens on OpenAIGatewayHandler; fixture openAIImagesFailoverAccountRepo from openai_images_failover_test.go L26; setting key service.SettingKeyOpenAIAPIKeyAlphaSearchResponsesBridgeEnabled; helpers newReplayableEndpointContext L194-L213 also reused by the official-HTTP integration test.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/handler/openai_request_rejected_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "74cbd5261b14975fe4c0ef750d26d2162e5dddee7b1489843c53116f6f163f97", - "review_fingerprint": "74cbd5261b14975fe4c0ef750d26d2162e5dddee7b1489843c53116f6f163f97", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "语义 400(request_rejected)终局测试(//go:build unit,下游新文件)。证明:被上游拒绝的请求覆盖 pool_mode 的 400 重试配置、只打到账号 1 绝不选账号 2(L63);上游 must-not-leak 细节不外泄,统一输出 OpenAIRequestRejectedCode/ClientMessage——非流式 JSON 400,流式为以 event: response.failed 开头的单一 SSE 终止(native/passthrough × json/sse × 两种上游 400 分类矩阵,L16-L109);OpsStreamError 记 IntendedStatus=400、CountTowardsSLA、UpstreamErrors[0].Kind=request_rejected 与 ContinuationDiagnostic.Classification(request_validation/unclassified_bad_request);SSE 线上 200 时 ops 错误日志仍记 400(L96-L104);流已开始时只追加一个终止事件(L111-L132);/v1/responses/compact 在 keepalive 提交 SSE 前保持 JSON+400(L134-L149)。主体 handleFailoverExhausted 与 request-rejected 分类在核心网关。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream test.", - "Call chain: service.NewOpenAIRequestRejectedError / OpenAIRequestRejectedCode / OpsStreamErrorKey / MarkOpenAICompactClientStream in backend/internal/service; parseResponsesFailedSSE in stream_error_event_test.go L36; openAIResponsesGenericBadRequestUpstream defined in openai_responses_failover_cancel_test.go L86; logOpsStreamError + opsErrorLogQueue in ops_error_logger*.go.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/handler/openai_responses_failover_cancel_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e2eb2344f70f7c77e14b21f5f7e9af063e0e0b887e01fdc0caa078c83207ebd7", - "review_fingerprint": "e2eb2344f70f7c77e14b21f5f7e9af063e0e0b887e01fdc0caa078c83207ebd7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Responses failover 取消与继续态终局测试。上游 aea725f 已有本文件(#4257 客户端断开回归:断开后不用已取消 context 重选账号、按 499 归类、保留真实 520 failover 事件;在线客户端按 [1,1,2,2] 重试后 502)。下游差异(+408/-5)新增:包装在 502 里的 previous_response_not_found 被重分类为继续态(400 invalid_request_error + OpenAIContinuationStateUnavailableCode,ops 事件 kind=continuation_state,绝不选账号 2,L371-L392);stream:true 预检失败(继续态或普通 400)在首字节前以恰好一个带内 response.failed SSE 终止且不泄漏上游细节(L398-L442);不透明加密工具链拒绝按 request_rejected 停止、不误判为继续态(L446-L473);旧 Laxa:model_not_supported 不跨账号重放且不透明重放归一 store=false(L475-L515)、预冷却 model_rate_limits 直接 400 不打上游(L517-L559)、混合组普通账号不进 Laxa 会话选择器(L561-L597);fixture 类型与 ListModelAvailabilityCandidates 桩、newOpenAIResponsesFailoverTestHandler 改为可注入账号。被测均为核心网关 failover 分类。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "git diff aea725f..worktree: upstream kept the two cancel/520 tests; downstream adds continuation-state/generic-400/model-not-supported upstream stubs, openAIResponsesCooledAccountRepo, ListModelAvailabilityCandidates stubs and six new tests; newOpenAIResponsesFailoverTestHandler gains variadic testAccounts.", - "Call chain: service.OpenAIContinuationStateUnavailableCode/OpenAIModelNotSupportedCode/OpsUpstreamErrorsKey in backend/internal/service; openAIHTTPPassthroughFailoverUpstream in openai_gateway_handler_test.go L2561; openAIImagesFailoverAccountRepo in openai_images_failover_test.go L26; helpers here are reused by openai_request_rejected_test.go and openai_reasoning_recovery_terminal_handler_test.go.", - "Low finding recorded: duplicated identical ListModelAvailabilityCandidates on the embedded repo type (L108-L126) and shadowing it on openAIResponsesCooledAccountRepo (L140-L158) -- redundant test-fixture code, no behavior difference.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/handler/openai_same_account_reacquire_slot_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a8ecbc3adc445145e7ecab0002ca02ec04abb55944baf7aab374f99ff37a2d69", - "review_fingerprint": "a8ecbc3adc445145e7ecab0002ca02ec04abb55944baf7aab374f99ff37a2d69", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "同账号重试的并发槽位重取测试(//go:build unit,下游新文件)。证明:acquireResponsesAccountSlotForSameAccountRetry 在槽位始终繁忙、WaitPlan 超时(20ms)时返回 openAISlotAcquireFailed 且不提交 streaming ping、不写任何响应字节、不 Flush——请求保持可重放以便切换账号(L82-L119);CountTokens 路径上账号 1 返回 401 切到账号 2、账号 2 的 503 触发同账号重取但槽位只允许一次获取(AcquireAccountSlot 仅首次为 true),耗尽后客户端只收到恰好一个 JSON 错误包体而不是叠加的两段 JSON(decoder 第二次 Decode 必须 io.EOF,L121-L169)。主体是核心网关的并发槽位与 failover 协作机制。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream test.", - "Call chain: acquireResponsesAccountSlotForSameAccountRetry in backend/internal/handler/openai_gateway_handler.go L2606; openAISlotAcquireFailed also consumed by grok_audio.go L257; fakeConcurrencyCache base stub in gateway_handler_warmup_intercept_unit_test.go L117; NewConcurrencyHelper/SSEPingFormatClaude in handler concurrency helper.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/handler/openai_ws_failover_policy.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ccd9e074463ba48aa217b8c7de17794989de771a441dd35b2f26157219691ea5", - "review_fingerprint": "ccd9e074463ba48aa217b8c7de17794989de771a441dd35b2f26157219691ea5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增源文件:OpenAI Responses WebSocket 首帧的账号切换重放安全策略。openAIWSPreviousResponseCanMove 对任何非空 previous_response_id 一律判不可迁移(无本地可信历史基线),否则用 service.ClassifyCindyContinuation 的 opaque/anchor 边界(无锚点、可换账号)加 conversation 引用检查决定;openAIWSLegacyLaxaReplaySafe 把同一边界应用到临时的 OpenAI 平台 Laxa 投影;openAIWSInitialAccountSwitchReplaySafe 在 previousResponseCanMove 之上重复同一分类。仅被核心 openai_gateway_handler.go 的 WS failover 分支调用,是宿主网关调度安全机制;Cindy 分类器本体在核心 service。发现:strictCindy 参数在 72edee8fb 修复统一分类后已完全失效(两个函数都不读它),调用方仍传 cindyIdentityGroup,见 findings。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream, whole file is the delta.", - "Call chain: callers openai_gateway_handler.go L3147-L3148 (initial frame), L3179/L3194/L3350 (legacy Laxa guard), L3713 (re-evaluation); classifier service.ClassifyCindyContinuation in backend/internal/service/openai_cindy_continuation.go L158; git show 72edee8fb removed the strictCindy branches and the old encrypted-state/coverage heuristics in favor of the classifier.", - "Low finding recorded: dead strictCindy parameter on both decision functions plus a redundant second classification in openAIWSInitialAccountSwitchReplaySafe; behavior today is safe (conservative), no security gap identified in the guard itself.", - "Statically read only; no runtime WS behavior claimed." - ] - }, - { - "path": "backend/internal/handler/openai_ws_failover_policy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0db0122b3f670deea4f56d9cfe9c35cf4f1ad8df3020824f09eddc88685f2521", - "review_fingerprint": "0db0122b3f670deea4f56d9cfe9c35cf4f1ad8df3020824f09eddc88685f2521", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "WS 首帧重放安全策略的表驱动单测(下游新文件)。证明:普通首轮可换账号;previous_response_id 锚点、不可迁移的工具续接、数组或单对象形式的 encrypted reasoning、item_reference、conversation 引用、compaction 加密载体、未见过的 call_id 工具输出都禁止换账号(TestOpenAIWSInitialAccountSwitchReplaySafe L9-L54、TestOpenAIWSPreviousResponseCanMove L56-L82、TestOpenAIWSFailoverDoesNotTreatExternalStateAsFullHistory L84-L94);旧 Laxa 沿用同一边界(L96-L106)。注意用例对 strictCindy 传 true/false 结果无差别,与该参数已失效一致(见 findings),测试无法区分该旗标。主体为核心 WS failover 策略。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S02-handler-openai-2-review.json", - "Upstream check: git ls-tree aea725f empty -- new downstream test.", - "Call chain: subjects openAIWSPreviousResponseCanMove/openAIWSInitialAccountSwitchReplaySafe/openAIWSLegacyLaxaReplaySafe in backend/internal/handler/openai_ws_failover_policy.go; classification via service.ClassifyCindyContinuation.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/handler/ops_error_logger.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0022f9df5dcfd6eff3566c3824b8811f69731b239ccbbd35065c2178c0b6e722", - "review_fingerprint": "0022f9df5dcfd6eff3566c3824b8811f69731b239ccbbd35065c2178c0b6e722", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "网关错误观测中间件与异步落库管道(2571 行,上游已有):有界 worker 队列(字节+条数双预算、批量 flush、脱敏计数)、opsCaptureWriter(sync.Pool + generation 租约防串请求,SSE 终止帧探测)、错误分类(phase/owner/source/SLA 业务限制)。下游相对上游(85 行插入/8 行改动):1) 新增 opsErrorClassificationKey/opsDedicatedEntryEnqueuedKey 与 setOpsErrorClassification 覆写机制,让 handler 落地更细的本地分类(如 model_capabilities/local_feature_gate);2) setOpsSelectedAccount 调 ObserveQuotaAccount、中间件入口 AttachQuotaActivity 挂配额活动;3) markOpsRoutingCapacityLimitedIfNoAvailable 从选号诊断补 Retry-After 头并结构化告警;4) 修正两处归因:applyOpsResponsesServerFailureMarker 仅凭匹配的请求本地 SLA 标记把 continuation 存储故障升级为 5xx server_error,UpstreamStatusCode 只在无尝试记录时才用语义状态回填(保留 account_auth 显式 0 与真实上游 502);5) shouldSkipFinalOpsFailure 对专用条目已入队场景去重;6) request_rejected/continuation_state_unavailable 两个码映射为 invalid_request/400。均为宿主观测/配额通用机制与修正,无插件业务规则(admin-observability 插件内无错误日志代码,不存在双执行器)。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta anchors vs aea725f: classification override keys+funcs L38-L40/L471-L491, ObserveQuotaAccount L501, Retry-After + selection diagnostics L524-L529, AttachQuotaActivity L1112-L1116, applyOpsResponsesServerFailureMarker L2081-L2100 (called L1160), UpstreamStatusCode nil-guard L1290-L1293, dedicated-entry dedup L1674-L1678, code mappings L2108/L2130.", - "Call chain: setOpsErrorClassification set by gateway_handler.go ModelCapabilities (asserted in gateway_models_test.go L337-L339); AttachQuotaActivity/ObserveQuotaAccount live in service/quota_activity.go; OpenAIRequestRejectedCode/OpenAIContinuationStateUnavailableCode from service openai continuation layer.", - "Checked for defects: capture-writer pool lease (generation+inFlight) prevents stale-handle writes; queue byte budget reserve/rollback is CAS-balanced on drop (L260-L269); no second executor found (rg over plugins/admin-observability has no error-log code).", - "No production behavior edit or test execution; review is static only." - ] - }, - { - "path": "backend/internal/handler/ops_error_logger_continuation_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e711d47c40697a11a15e19b384b0a531ef76df0ca5068964772934c29c9e87d3", - "review_fingerprint": "e711d47c40697a11a15e19b384b0a531ef76df0ca5068964772934c29c9e87d3", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新测试文件(213 行),证明中间件对 Responses continuation/rejection 终止帧的归档修正:wire 200 下按语义状态落库(request_rejected/continuation_unavailable → 400/P3,不再以 502/P1 复现),已记录的上游 502 尝试状态不被客户端语义状态覆盖,未知码不按 message 归类仍为 upstream_error/502;continuation 存储故障经 handleFailoverExhausted 保持 503/P1 api_error;applyOpsResponsesServerFailureMarker 忽略不匹配码、非 SLA 标记与过期 WebSocket turn。经真实 gin router + 中间件 + 测试队列走全链路并断言只入队一条(终止帧解析与流标记不重复落库)。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Key assertions: semantic 400 persistence L119-L127, upstream 502 preservation L128-L135, unknown code fallback L57-L65, store-outage 503/P1 via handleFailoverExhausted L143-L179, marker guard matrix L181-L213.", - "These prove exactly the ops_error_logger.go downstream fixes (applyOpsResponsesServerFailureMarker + UpstreamStatusCode nil-guard + dedicated-entry dedup); subject is core gateway observability, no plugin rule.", - "New downstream file (absent from aea725f); test not executed (static read only)." - ] - }, - { - "path": "backend/internal/handler/ops_error_logger_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "df6fde7bf55adaa453af6aa1180cb58b9df67f2a3df505a1a2eb26089ea5e622", - "review_fingerprint": "df6fde7bf55adaa453af6aa1180cb58b9df67f2a3df505a1a2eb26089ea5e622", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "错误观测管道主测试(2202 行,上游已有):队列字节预算/满队降级/启停分支、capture writer 池化复位与超限帧有界性、SSE 终止帧跨 chunk 解析、脱敏(authorization/api_key REDACTED、截断 JSON 片段替换 payload_truncated)、分类矩阵(本地鉴权/业务限流/路由容量/本地模型配置/ingress 白名单/上游归因/带内 RequestScoped)。下游相对上游仅 36 行:原 StreamFailureUsesTerminalErrorOverAttemptContext 改名并翻转断言——UpstreamStatusCode 保留真实上游 502 而非被语义 400 覆盖(对应源文件 nil-guard 修正);新增 TestOpsErrorLoggerMiddleware_PersistsLocalErrorClassification 证明 setOpsErrorClassification 覆写在 ErrorType 落库生效且不带上游归因。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta vs aea725f: rename+assertion flip at L538-L566 (now requires *UpstreamStatusCode == 502 BadGateway), new classification-override test L1916-L1946 asserting ErrorType=model_capabilities/local_feature_gate, InboundEndpoint=/v1/models/capabilities, empty UpstreamEndpoint.", - "Remaining ~2100 lines are upstream v0.2.7 coverage read in full: queue budget L56-L96, pool reset L185-L211, sanitization L213-L228/L1843-L1857, classification matrices L955-L1593, in-band stream error semantics L2032-L2192.", - "Static read only; the test was not executed." - ] - }, - { - "path": "backend/internal/handler/plugin_contract_fixture_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3ad9c3d5087a696d3a78ea2ff85afd4c434c93077845e290934ffdbb3f161769", - "review_fingerprint": "3ad9c3d5087a696d3a78ea2ff85afd4c434c93077845e290934ffdbb3f161769", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "handler 包测试引导文件(16 行,下游新文件):init 安装 testextensions 进程内测试扩展宿主,enableImageStudioPolicy(t) 以 ImageToolsConfig{StudioEnabled:true} 安装 image-tools 策略并在 cleanup 恢复默认 fixture。这是扩展宿主契约的测试装置,被本切片 image_studio_* 测试引用;不含业务规则。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Whole file: init() testextensions.Install (L10) and enableImageStudioPolicy L12-L16 using extensionv1.ImageToolsConfig; consumed by image_studio_executor_test.go / image_studio_job_handler_test.go.", - "New downstream file (absent from aea725f); test fixture not executed (static read only)." - ] - }, - { - "path": "backend/internal/handler/remote_skill_handler.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "e4b1f31586508c9c9fd5cffbc7df2af23a9684aea561b3c18fb7585f1fa587fc", - "review_fingerprint": "e4b1f31586508c9c9fd5cffbc7df2af23a9684aea561b3c18fb7585f1fa587fc", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/remote_skill_handler_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9b0e56b390801c777c07424755c02e92ff668baa70f30adb1daf026ccc1d23ca", - "review_fingerprint": "9b0e56b390801c777c07424755c02e92ff668baa70f30adb1daf026ccc1d23ca", - "review_status": "pending" - }, - { - "path": "backend/internal/handler/request_body_limit.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c1345fbb5206f494fef6985aead7f1fec8fc3dbb45dc8bde0ca3edba75e58932", - "review_fingerprint": "c1345fbb5206f494fef6985aead7f1fec8fc3dbb45dc8bde0ca3edba75e58932", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "请求体大小限制与读体错误诊断辅助(82 行,上游已有)。下游相对上游新增三个纯函数:classifyRequestBodyReadError(unexpected_eof/eof/context_canceled/deadline_exceeded/other)、requestBodyReadMetrics(从 RequestBodyReadError 取 stage 与收到/解码字节数)、classifyRequestContentEncoding(identity/zstd/gzip/deflate/other),供 openai_gateway_handler.go 输出不含请求内容的读体失败诊断日志。上游已有的 MaxBytesError 提取与 413 文案不变。通用网关机制。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta vs aea725f: 41 insertions — the three classifier helpers L23-L59; callers traced with rg to backend/internal/handler/openai_gateway_handler.go only.", - "Diagnostics are content-free by construction: only errors.Is classes, stage and byte counts are surfaced, never body bytes.", - "No production behavior edit or test execution; review is static only." - ] - }, - { - "path": "backend/internal/handler/request_body_limit_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "96c215e3732ae1e2cbb7dbf5f9f70a3cfa93e1d886c0044d0fa3d0fc4ed9d627", - "review_fingerprint": "96c215e3732ae1e2cbb7dbf5f9f70a3cfa93e1d886c0044d0fa3d0fc4ed9d627", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "读体限制测试(72 行,上游已有)。上游部分证明超限请求经 middleware.RequestBodyLimit 返回 413 且文案含限额;下游新增两测试:RequestBodyReadDiagnosticsAreContentFree 证明诊断只暴露 stage/字节数并保留 errors.Is 链,ClassifyRequestContentEncoding 证明编码归类(大小写与空白容忍、x-gzip→gzip、未知→other)。被测对象为核心网关请求体机制。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta vs aea725f: 27 insertions — TestRequestBodyReadDiagnosticsAreContentFree L49-L63 and TestClassifyRequestContentEncoding L65-L72.", - "Static read only; the test was not executed." - ] - }, - { - "path": "backend/internal/handler/setting_handler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "19f4d314f6c23aef4d44afd3b9dc072cd1d83102ed4c7b4bf144e7c61afa1277", - "review_fingerprint": "19f4d314f6c23aef4d44afd3b9dc072cd1d83102ed4c7b4bf144e7c61afa1277", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-ui-adapter", - "reason": "公开设置处理器(193 行,无需认证,上游已有)。下游相对上游新增插件 UI 桥接:pluginManager 字段(wire.go ProvideSettingHandler L176-L178 注入)、GetPublicPluginContributions 返回公开插件贡献(no-store)、GetPublicPluginThemeAsset 按 id/revision/path 提供插件主题资产(css/woff2,附 nosniff 与 same-origin CORP 头),以及公开设置里新增 ImageStudioEnabled 开关透出。资产读取的防目录穿越/清单白名单/sha256 校验在 service.PluginManager.ReadPublicThemeAsset(plugin_theme.go L34-L66)实现,handler 只做参数解析与响应头。通用的宿主-插件 UI 桥接,不归属单一插件域,故 adapter/core-ui-adapter。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta vs aea725f: 33 insertions — pluginManager field L19, GetPublicPluginContributions L25-L32, GetPublicPluginThemeAsset L34-L53, ImageStudioEnabled L147; routes at server/routes/auth.go L247-L248 (public settings group).", - "Security check done: ReadPublicThemeAsset enforces safePluginRelativePath, revision match, per-plugin public theme contribution allowlist and manifest sha256 digest, so the unauthenticated *path param cannot traverse (plugin_theme.go L34-L66) — no finding.", - "The rest of the file (GetPublicSettings DTO, email unsubscribe with html.EscapeString) is upstream core content unchanged in substance.", - "No production behavior edit or test execution; review is static only." - ] - }, - { - "path": "backend/internal/handler/stream_error_event.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "caf83c8fe7dc0e89048bce6d02711925ae498d1e200c7e3ffd3aabebe82e031b", - "review_fingerprint": "caf83c8fe7dc0e89048bce6d02711925ae498d1e200c7e3ffd3aabebe82e031b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI Responses 协议 response.failed 终止帧发射器(210 行,上游已有):HTTP 200 固化后只能以 SSE 事件回报错误,字段对齐 apicompat(sequence_number/created_at 必写,兼容 grok-build 等严格反序列化客户端)。下游相对上游:error 子对象新增 retryable(omitempty);抽出 writeResponsesFailedSSEWithDetails,在响应未提交时补设 SSE 头(Content-Type/Cache-Control/X-Accel-Buffering),使 stream:true 请求在首个上游字节前失败也能发合法终止帧;code 为空时先经 mapResponsesErrorCode 从 errType 推导;新增 inboundResponsesStreamRequested 从 opsStreamKey 读已解析的流意图(不重读已消费的 body)。核心网关协议机制。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S05-handler-rest-2-review.json", - "Delta vs aea725f: 38 insertions/4 deletions — Retryable field L19, pre-commit SSE headers L75-L79, code fallback L81-L83, inboundResponsesStreamRequested L151-L158.", - "Consumers traced: ops_error_logger_continuation_test.go drives writeResponsesFailedSSE through the middleware; handleFailoverExhausted emits via this writer for continuation-store outages.", - "No production behavior edit or test execution; review is static only." - ] - }, - { - "path": "backend/internal/handler/wire.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c14c9649d75a9440e99ef3ebb5fa9aca2c9359672df215a83eea279561872ff3", - "review_fingerprint": "c14c9649d75a9440e99ef3ebb5fa9aca2c9359672df215a83eea279561872ff3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Dependency assembly connects the same plugin manager to gateway, public settings and admin operations; the account task runtime wraps the existing core executor in PluginJobExecutor. Image/remote-skill endpoints and host IO runtime are separately constructed, while native Anthropic forwarding and telemetry adapters retain their dedicated services. Original admin step-up and notification dependencies remain; no route middleware is bypassed here.", - "evidence": [ - "Full file and upstream delta read. Current Wire regeneration for server cleanup compiled this provider graph; no startup, model, database or handler integration test is implied by static wiring review.", - "artifacts/evidence/v027-host-job-wiring-static-review.json" - ] - }, - { - "path": "backend/internal/payment/provider/alipay_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7b7aead944c93e6cc44e3caf1d17fc620b7e240f2a4f4120633cf1ff16005a6b", - "review_fingerprint": "7b7aead944c93e6cc44e3caf1d17fc620b7e240f2a4f4120633cf1ff16005a6b", - "review_status": "pending" - }, - { - "path": "backend/internal/payment/provider/easypay_refund_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bf9e5e580ac757aa003a08fc7d02f952a42c68b4f77bdf8250b1f3683fdba3e7", - "review_fingerprint": "bf9e5e580ac757aa003a08fc7d02f952a42c68b4f77bdf8250b1f3683fdba3e7", - "review_status": "pending" - }, - { - "path": "backend/internal/payment/provider/wxpay_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fd9bc7b41195ddbc7dde2dd0c9a48afd8a6d61683f5e11d0ea0474c1b9172e5f", - "review_fingerprint": "fd9bc7b41195ddbc7dde2dd0c9a48afd8a6d61683f5e11d0ea0474c1b9172e5f", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/antigravity/client_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "af307700a4d3dd11bc0000b016a9b8bf722af18d7cdddde81b542c27c5ed8774", - "review_fingerprint": "af307700a4d3dd11bc0000b016a9b8bf722af18d7cdddde81b542c27c5ed8774", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/antigravity/oauth_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "93fb9ad91f1dc5a2a0a67548046381dbb5bff1ef7d274b260f1513213109c82c", - "review_fingerprint": "93fb9ad91f1dc5a2a0a67548046381dbb5bff1ef7d274b260f1513213109c82c", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/antigravity/request_transformer_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f7ef972bbc0afdb753a44e159a2080363fa2c95fd03d7e5c1ecdf0f346988c46", - "review_fingerprint": "f7ef972bbc0afdb753a44e159a2080363fa2c95fd03d7e5c1ecdf0f346988c46", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/apicompat/agent_stream_terminal_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fc65173840acb220ed4c47bba5f6d0fce7094ce281a52293ad4b130a74a5b80e", - "review_fingerprint": "fc65173840acb220ed4c47bba5f6d0fce7094ce281a52293ad4b130a74a5b80e", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/apicompat/agent_tool_history_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1e11fbb197e2dd14e23d95a7189747c6e4c26e3c33d3beb2ecc10a3fccb307ac", - "review_fingerprint": "1e11fbb197e2dd14e23d95a7189747c6e4c26e3c33d3beb2ecc10a3fccb307ac", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/apicompat/anthropic_responses_fidelity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "78cf3e29d39d4fea90e16f7d2c352ef4f47c4d42590180a531239794de0fc2b9", - "review_fingerprint": "78cf3e29d39d4fea90e16f7d2c352ef4f47c4d42590180a531239794de0fc2b9", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/apicompat/anthropic_responses_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8e4754f8bada293f82330d3b32f73aad0999853b12fdffc339198f553247050a", - "review_fingerprint": "8e4754f8bada293f82330d3b32f73aad0999853b12fdffc339198f553247050a", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/apicompat/anthropic_to_responses.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "aee474b6d1965c0a1c942ce16a0fecd1635fae504426cd5e10dd07e60cbf3bc3", - "review_fingerprint": "aee474b6d1965c0a1c942ce16a0fecd1635fae504426cd5e10dd07e60cbf3bc3", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/apicompat/chat_terminal.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5c2d4516013dc4805db6dca4c2a1d1927bb4f8b219626ef5d86f68eb1bdabeda", - "review_fingerprint": "5c2d4516013dc4805db6dca4c2a1d1927bb4f8b219626ef5d86f68eb1bdabeda", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_responses_bridge.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d118168eaa11a53440f5de2a4813f76236f041c69128963f51acb3346608da2a", - "review_fingerprint": "d118168eaa11a53440f5de2a4813f76236f041c69128963f51acb3346608da2a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Responses↔Chat Completions 双向桥: 请求方向把 Responses 请求/历史降级为 chat messages+tools (custom/namespace/tool_search 摊平、DeepSeek reasoning_content 回填、工具输出媒体搬移), 回程把非流式响应与 SSE 分片还原为 Responses 项/事件。下游相对上游 aea725f: 新增 fail-closed 门 (previous_response_id、需原生的 reasoning/tools 经 responses_capabilities.go 判定后返回 unsupported_feature; 不可表达的 tool_choice 返回 invalid_request_error 而非静默丢弃), 新增 validateResponsesChatToolHistory 把重复 call_id/缺失输出/孤儿输出一律判 invalid_tool_history (取代上游的 invalidFunctionCallIDs 静默跳过与 normalize 丢弃自愈), 未知非 message 项与加密 reasoning 缓存未命中改为 unsupported_input_item; 回程改用 chat_terminal.go 的 ChatCompletionTerminal 语义 (finish_reason 缺失→failed, reasoning-only 不再合成 message, 空 choices→upstream_empty_response, 工具元数据/参数不全→upstream_invalid_tool_call), 删除 emptyResponsesMessageOutput 与 synthesizeChatReasoningFallbackMessage, 流式新增 Failure 字段、负索引与已宣告工具身份变更检测, incomplete/failed 时不再关闭工具项且输出项标 incomplete, chatOutput/closeChatToolItems 按 output_index 稳定排序。这是宿主 OpenAI 协议网关的通用转换机制 (调用方 service/openai_gateway_responses_chat_fallback.go 与 openai_gateway_chat_completions.go); Codex 客户端工具形态的处理在上游已存在, 不属于任何插件域业务。仅静态阅读, 未执行测试; 缺失 tool_call.id 兜底被移除一事记入 findings (low)。", - "evidence": [ - "Full-file static review (L1-L2341, 5 sequential chunks): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+185 -124): +responsesReasoningChatCompatible L45-L55, +previous_response_id/reasoning/tools 原生门 L67-L72/L97-L99, +tool_choice 拒绝 L121-L126, +validateResponsesChatToolHistory L435-L463 并在 L373 调用, function_call/tool_search_call 非法参数改为返回 invalid_tool_history L536-L539/L565-L567, 未知项 L657-L660 与 encrypted-only reasoning L531-L533 → unsupportedResponsesInput, ChatCompletionsResponseToResponses 终态改造 L1400-L1440, -emptyResponsesMessageOutput/-synthesizeChatReasoningFallbackMessage, +Failure L1675, ValidateToolCallArguments 收紧 L1698-L1718, 流式负索引/身份变更 L1787-L1812, FinalizeChatCompletionsResponsesStream 用 state.terminal() L1847-L1933, +terminal() L1935-L1951, announceChatToolItem 去掉 force 参数并要求 ID+Name L2054-L2062, chatOutput 稳定排序 L2276-L2296", - "call chain: ChatCompletionTerminalForReason/FailedChatCompletionTerminal 定义于 apicompat/chat_terminal.go L12-L27; ResponsesReasoningRequiresNative/ResponsesToolsRequireNative/unsupportedResponsesInput 定义于 responses_capabilities.go L15/L27/L69; 外部调用方仅 service/openai_gateway_responses_chat_fallback.go (L72 请求转换, L198 非流式回程, L278/L295/L318/L336 流式, L442 reasoning 缓存) 与 service/openai_gateway_chat_completions.go L172/L204; normalizeChatMessages 另被 chatcompletions_anthropic_bridge.go L146 复用, 故其孤儿/未应答丢弃分支非死代码", - "boundary: plugins/codex-runtime manifest.source.json 的能力为 292 票据/identity/transport/recovery (extensions.request.v1 等), 不含协议转换; 本文件无插件重复执行器", - "Static read only; no test, build or production execution; worktree untouched." - ] - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_responses_bridge_custom_tools_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2703d3f79d7995b0b39af506767d592a1173a164082a8d00414154992b97dbe2", - "review_fingerprint": "2703d3f79d7995b0b39af506767d592a1173a164082a8d00414154992b97dbe2", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Responses→chat 桥中 custom/freeform、namespace、tool_search、additional_tools 工具的双向转换测试 (Codex exec 工具降级为 function、摊平名 64 字符哈希截断、回程还原 custom_tool_call/tool_search_call/namespace function_call、SSE 白名单落线、迟到名字延迟宣告、撞名显式拒绝、tool_search 发现晋升)。下游相对上游 aea725f 的改动全部是把 '丢弃' 语义改为 '拒绝' 语义的断言: 仅含 web_search/image_generation 的请求现在 require.Error (RejectsNonConvertibleTools), 指向被丢弃工具/不存在名字/未声明 tool_search 的 tool_choice 现在 require.Error 且 out 为 nil (RejectsUnrepresentableToolChoice, ToolSearchToolChoiceMapsToProxy 第二段); 新增 finalizeCompleteChatToolFixture 显式设 FinishReason=tool_calls 后再 Finalize (因为下游 terminal() 在 finish_reason 缺失时判 failed), 并从 NamespaceToolFlattensChildren 夹具中删除了 custom 子工具。这些断言证明 bridge.go 下游 fail-closed 改造的行为, 主体是核心协议网关。测试仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L1167, 3 sequential chunks): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+29 -28): +finalizeCompleteChatToolFixture L15-L19 并替换全部 11 处 FinalizeChatCompletionsResponsesStream 直呼; DropsToolChoiceWhenNoConvertibleTools→RejectsNonConvertibleTools L167-L181; DropsToolChoiceForDroppedTool→RejectsUnrepresentableToolChoice L856-L913 (三段 require.NoError/Empty 改 require.Error/Nil); ToolSearchToolChoiceMapsToProxy 未声明段 L926-L934 改为拒绝; NamespaceToolFlattensChildren 夹具 L543-L550 删除 custom 子工具", - "被测对象: bridge.go ResponsesToChatCompletionsRequestWithOptions L63-L131 (tool_choice 拒绝分支 L121-L126)、responsesToolsToChatTools L1105-L1187、announceChatToolItem/closeChatToolItems、ResponsesEventToSSE (responses_stream_event_wire.go); 断言证明的是 chat 上游不可表达时整请求 400 而非静默降级", - "Test source statically read only; not executed; no worktree modification." - ] - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_responses_bridge_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4a5406314ad6bdb527f0acdb4730eb5e1d0643d2c175fe28e1491e612ee4b913", - "review_fingerprint": "4a5406314ad6bdb527f0acdb4730eb5e1d0643d2c175fe28e1491e612ee4b913", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Responses→chat 桥基础行为测试: developer→system 角色映射、前导多条 developer 合并为单条 system、会话中段 developer/system 降为 user、text.format json_object/json_schema 映射、parallel_tool_calls 透传、非流式 finish_reason=length 时跳过参数非法的 tool call。下游相对上游 aea725f: SkipsInvalidHistoricalFunctionCall/SkipsInvalidEmptyCallIDOutput 改名为 Rejects* 并改用共享助手 requireInvalidResponsesToolHistory (agent_tool_history_test.go L10) 断言 invalid_tool_history/param=input, 证明历史中非法 JSON arguments 的 function_call 不再被静默剔除而是整请求拒绝; KeepsChatCompletionRoles 夹具把裸 role=tool 项换成 function_call+function_call_output 配对 (因下游 validateResponsesChatToolHistory 会拒绝无 tool_call_id 的 tool 消息)。测试主体是核心协议桥。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L220): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+6 -16): L20-L39 两个 Skips* 测试改为 Rejects* 并委托 requireInvalidResponsesToolHistory; L65-L78 KeepsChatCompletionRoles 夹具改为 call_fixture 配对, 期望角色序列仍为 system/user/assistant/tool", - "被测代码: bridge.go buildChatMessagesFromItems function_call 分支 L536-L539 (非法 JSON → invalid_tool_history), validateResponsesChatToolHistory L435-L463 (call_id 为空 → invalid), normalizeResponsesDerivedChatMessageRoles L387-L433", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_responses_reasoning_cache_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "77f19760928cb6e747ab00d5f3b23dc5dfe1442c2dcd8e2d1519981ce9abc6e8", - "review_fingerprint": "77f19760928cb6e747ab00d5f3b23dc5dfe1442c2dcd8e2d1519981ce9abc6e8", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "网关侧 reasoning 缓存钩子 (ResponsesToChatOptions.ReasoningContentByID) 测试: 加密-only reasoning 项经缓存命中回填 reasoning_content、明文 summary 优先且不触发查找、链式工具调用回放本轮 reasoning、ExtractResponsesReasoningItem 解析。下游相对上游 aea725f 仅改一处: MissKeepsOriginalBehavior→MissRequiresNative, 缓存未命中 (含 nil options 旧路径) 现在断言返回 ResponsesConversionError code=unsupported_input_item 且 out 为 nil, 证明 bridge.go L531-L533 '加密 reasoning 无法回填则拒绝降级' 的 fail-closed 行为, 避免 DeepSeek thinking 模式因缺 reasoning_content 400。被测对象为核心协议桥; 缓存本体在 service/openai_gateway_responses_chat_fallback.go L442 附近, 不在本文件。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L163): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+9 -7): L44-L69 MissRequiresNative 断言 require.Nil(out) + ErrorAs ResponsesConversionError + Code==unsupported_input_item, legacy nil-options 路径同样", - "被测代码: bridge.go reasoning 分支 L515-L535 (extractResponsesReasoningText → opts.ReasoningContentByID → encrypted_content 非空则 unsupportedResponsesInput), ExtractResponsesReasoningItem L1010-L1023, lastTurnReasoning 回放 L478-L490", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_responses_request_invariants_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "dd618b16749ebda3853a87009e6a58b775cd8544b69b67eb44c809977d510544", - "review_fingerprint": "dd618b16749ebda3853a87009e6a58b775cd8544b69b67eb44c809977d510544", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "以 Codex 真实请求形状为金样本, 校验 Responses→chat 转换后满足 DeepSeek/OpenAI Chat 不变量 (assistant tool_calls 后紧跟按序 tool 回复、无连续 assistant、无孤儿 tool)。下游相对上游 aea725f: web_search_call 夹在 function_call 与输出之间的样本从 '保持相邻性' 改为断言 unsupported_input_item (托管工具历史无法无状态表达); 部分并行未应答、末尾悬空 tool_call、孤儿输出三例从 '被丢弃' 改为 requireInvalidResponsesToolHistory 断言整请求拒绝。这些断言证明 bridge.go validateResponsesChatToolHistory 与未知项拒绝的下游修正; 保留的 SingleToolCall/ParallelToolCalls/MessageBetweenToolCallAndOutput 仍验证 normalize 的重排能力。核心协议桥测试, 仅静态阅读未执行。", - "evidence": [ - "Full-file static review (L1-L175): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+18 -30): L90-L105 UnknownItemBetweenToolCallAndOutputRequiresNative 断言 msgs nil + unsupported_input_item; L147-L156 PartialParallelRejectsUnansweredCall、L158-L166 DanglingToolCallRejected、L168-L175 NormalizeRejectsOrphanToolReply 全部委托 requireInvalidResponsesToolHistory (agent_tool_history_test.go L10-L18: code=invalid_tool_history, param=input)", - "被测代码: bridge.go L373 validateResponsesChatToolHistory 调用点、L657-L660 非 message 项 unsupportedResponsesInput、normalizeChatMessagesWithToolOutputMedia L894-L966 (MessageBetweenToolCallAndOutput 仍依赖其重排)", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_responses_stream_lifecycle_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4adb22b3829c2af5bf91cbe93db845bb150e147b8dba99f794974a4ad69e996c", - "review_fingerprint": "4adb22b3829c2af5bf91cbe93db845bb150e147b8dba99f794974a4ad69e996c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Chat SSE→Responses 事件的生命周期测试: reasoning 项先 added 再 delta、工具调用完整收尾 (arguments.done+output_item.done)、GLM 首分片参数不重复累积、非法参数在 Finalize 前被 ValidateToolCallArguments 拒绝、SSE 线上 added 事件带 arguments 空串。下游相对上游 aea725f: ReasoningOnlySynthesizesVisibleText→ReasoningOnlyPreservesIncompleteWithoutSyntheticAnswer (finish_reason=length 的纯 reasoning 流现在断言无 output_text.delta/done、无 message done, 终态事件为 response.incomplete 且 Output 仅 1 个 reasoning 项), ReasoningOnlyBlank 终态改为 response.failed 且仅 reasoning 项, ValidToolCallAtOutputLimit 断言不再发 function_call_arguments.done ('length 截断不得授权执行') 且终态为 response.incomplete。证明 bridge.go 删除 synthesizeChatReasoningFallbackMessage、terminal() 语义与 incomplete 时跳过 closeChatToolItems 的下游修正。核心协议桥测试, 静态阅读未执行。", - "evidence": [ - "Full-file static review (L1-L306): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+10 -14): L48-L86 断言反转 (sawTextDelta/sawTextDone/sawMessageDone 全为 false, case 改为 response.incomplete, Output len 1), L88-L102 blank reasoning 改为 response.failed, L237-L283 ValidToolCallAtOutputLimit 改为 require.False(sawArgsDone) 与 response.incomplete", - "被测代码: bridge.go FinalizeChatCompletionsResponsesStream L1847-L1933 (terminal.Status!=completed 时不调用 closeChatToolItems, 事件类型来自 terminal.EventType), terminal() L1935-L1951 (Text 空且无工具 → upstream_empty_response), chat_terminal.go L12-L23 (length→response.incomplete/max_output_tokens)", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_responses_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d8ed735cb425c5f0835ad372bbdda3c353c3651cbb5f621fab19df77757e1134", - "review_fingerprint": "d8ed735cb425c5f0835ad372bbdda3c353c3651cbb5f621fab19df77757e1134", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Chat Completions↔Responses 转换的主测试集 (1847 行): ChatCompletionsToResponses 的 system/tool/文件/图片/strict/legacy functions/response_format/reasoning 模型 temperature 剥离/空 content 非 null 等请求映射, ResponsesToChatCompletions 的用量细节 (cached/reasoning/audio/prediction tokens)、web_search 输出, ResponsesEventToChatChunks 流式状态机 (output_index→tool index 映射、终态 finish/usage 分片、response.done 兼容), BufferedResponseAccumulator 缓冲补全。下游相对上游 aea725f 仅改一个测试: DeepSeekReasoningOnlyFallsBackToMessageText→ReasoningOnlyIsNotAnAnswer, 纯 reasoning、空 content 的非流式 chat 响应现在断言 Output 仅 1 个 reasoning 项、Status=failed、Error.Code=upstream_empty_response, 证明 bridge.go ChatCompletionsResponseToResponses L1428-L1437 'reasoning 不算答案' 的下游修正; 其余约 1840 行与上游一致 (被测 chatcompletions_to_responses.go/responses_to_chatcompletions.go 属本切片后续文件)。核心协议桥测试, 静态阅读未执行。", - "evidence": [ - "Full-file static review (L1-L1847, 4 sequential chunks): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+4 -5): 仅 L518-L541 一处, require.Len(Output,1)+failed+upstream_empty_response 取代原 Output len 2 与 message 文本等于 reasoning 的断言", - "被测代码: bridge.go ChatCompletionsResponseToResponses L1374-L1443 (deliverable 判定 L1428-L1437), chatMessageToResponsesOutput L1453-L1543 (text 为空不再合成 message L1467); 其它断言对应 chatcompletions_to_responses.go ChatCompletionsToResponses 与 responses_to_chatcompletions.go ResponsesEventToChatChunks/BufferedResponseAccumulator", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_responses_tool_output_media_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "78e3b9042cee2711cf4f8c577f66dcc58168a46148731ffe834f5ca9a0a6569e", - "review_fingerprint": "78e3b9042cee2711cf4f8c577f66dcc58168a46148731ffe834f5ca9a0a6569e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "工具输出媒体搬移测试: function/custom/tool_search 输出中的 input_image/image_url (数组、顶层对象、content 包装、JSON 字符串、裸 data URL) 被替换为占位文本并以 user 消息紧随 tool 回复之后, 并行批次按调用顺序归并, 无媒体输出保留原字节, tool 消息内容绝不含被提取的媒体 URL。下游相对上游 aea725f: DropsOrphanAndUnansweredCallMedia→RejectsOrphanAndUnansweredCallMedia、DuplicateCallIDIsLastWins→DuplicateCallIDIsRejected, 孤儿输出、未应答并行调用、重复 call_id 输出 (后媒体覆盖前媒体/后文本清空前媒体) 四例全部改为 requireInvalidResponsesToolHistory 断言整请求拒绝, 证明 bridge.go validateResponsesChatToolHistory 对媒体路径同样生效, 且 mediaByCallID 的 last-wins 覆盖不再可达。核心协议桥测试, 静态阅读未执行。", - "evidence": [ - "Full-file static review (L1-L302): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+6 -22): L163-L176 两个子测试改为 requireInvalidResponsesToolHistory; L226-L241 重复 call_id 两个子测试改为拒绝, 删除 last.png/latest text 的 last-wins 断言", - "被测代码: bridge.go extractToolOutputMedia L723-L764, rewriteToolOutputMediaValue L779-L816, normalizeChatMessagesWithToolOutputMedia 媒体 user 消息拼装 L943-L960, validateResponsesChatToolHistory L435-L463 (answered 为 true 时再次出现 → invalid)", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/chatcompletions_to_responses.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "52d9432619ec38ca658db1c526506f1914a645972a7dae2a44235bd13990cad6", - "review_fingerprint": "52d9432619ec38ca658db1c526506f1914a645972a7dae2a44235bd13990cad6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Chat Completions 请求→Responses 请求的转换 (messages→input items, tools/legacy functions→ResponsesTool, response_format→text.format, max_tokens 下限钳制, reasoning 模型剥离 temperature/top_p, store=false + include reasoning.encrypted_content)。下游相对上游 aea725f 改两处: (1) reasoning 不再由 reasoning_effort 新建 {effort, summary:auto} 覆盖, 而是 req.Reasoning.Clone() 保留客户端嵌套 reasoning 对象的全部成员 (mode/context/未知扩展), 仅在 reasoning_effort 非空时覆盖 effort, 且 summary 只在客户端未显式给出 (HasField) 时补 auto; (2) 新增导出 ChatMessageResponsesInput 把单条 Chat 消息投影为 Responses 输入项 JSON, 供 service/openai_chat_reasoning_replay.go L314/L324 的有状态 reasoning 回放桥整轮替换 assistant 项。均为宿主协议网关的通用机制, 无插件重复实现。仅静态阅读, 未执行测试。", - "evidence": [ - "Full-file static review (L1-L533): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+29 -4): L65-L76 out.Reasoning = req.Reasoning.Clone() + effort 覆盖 + !HasField(summary) 才补 auto; L119-L134 +ChatMessageResponsesInput", - "call chain: Clone/HasField 定义于 responses_reasoning.go L55-L79; ChatCompletionsRequest.Reasoning 字段见 types.go; ChatMessageResponsesInput 调用方 rg: service/openai_chat_reasoning_replay.go L314、L324 (非测试代码中唯一调用方); 行为由 responses_reasoning_test.go TestResponsesReasoningConfigurationChatMerge 覆盖 (静态阅读)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_agent_message_capabilities_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "003d0f42bbf475a8e3a2a9b833bc802eab294e100430bc4e23b7cf110fa31a8d", - "review_fingerprint": "003d0f42bbf475a8e3a2a9b833bc802eab294e100430bc4e23b7cf110fa31a8d", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "全文52行复核:3个明文正控调用真实转换器并比较角色、数量和原字节/次序,9个反控明确覆盖encrypted单独/混合/对象、未知类型、图片、非法text及native-only历史;不是仅mock能力判断。纯内存输入,无HTTP或模型请求,最终修订后的12叶场景有实际通过记录。", - "evidence": [ - "artifacts/evidence/v027-astra-protocol-completion-review.json#PKG-FINAL-TARGETED", - "Parent full fixture review; final SHA verified; passing methods not repeated." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_capabilities.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d70ee0808f4855da001baab2703d6b5882300617884b5dd3b25cefe08c909193", - "review_fingerprint": "d70ee0808f4855da001baab2703d6b5882300617884b5dd3b25cefe08c909193", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "全文107行复核:协议可表达性检查保留reasoning未知配置、hosted tools及opaque状态的native要求;新增agent_message只接受bridge现有可无损保序的明文字符串/文本片段,未知类型、对象、图片、密文及混合密文仍native。空内容不虚构历史;该文件没有网络、凭据、账号/模型身份重写或插件业务策略,错误为固定安全文案。有效文本实际转换及服务选路反控已通过;不能把复制密文当成解密。", - "evidence": [ - "artifacts/evidence/v027-astra-protocol-completion-review.json#S45-AGENT-MESSAGE-ROUTING", - "Parent read all current source and both capability fixtures; final frozen hash verified before commit, no repeat of passing Go tests." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_chat_protocol_completion_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f23fbb5a552d91fed26e3c004b5d03a04e379bbbfec4229805cb0071d7881173", - "review_fingerprint": "f23fbb5a552d91fed26e3c004b5d03a04e379bbbfec4229805cb0071d7881173", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "全文83行复核:用真实事件触发参数矛盾、call_id变化和terminal遗漏,不直接设置ProtocolError;错误后迟到complete及重复finalize仍不能发正常finish/usage。完整工具正控保留实际ID、名称、完整参数、一份usage及一次tool_calls收尾。两个方法最终源码与实际绿结果对应,无外部依赖。", - "evidence": [ - "artifacts/evidence/v027-astra-protocol-completion-review.json#PKG-GREEN-FAILURES", - "artifacts/evidence/v027-astra-protocol-completion-review.json#PKG-FINAL-TARGETED", - "Parent full fixture read and common-finalizer region review; no repeated business test." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_created_at_wire_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0e0d4ce244d165fe2414984f05c8f0e74a6e06b9a5fb8fad5edc3e4db1fb67dd", - "review_fingerprint": "0e0d4ce244d165fe2414984f05c8f0e74a6e06b9a5fb8fad5edc3e4db1fb67dd", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "issue #5601 的 created_at 线格式守卫测试: 网关合成的 Responses 对象 (Chat→Responses、Anthropic→Responses 两桥) 在 response.created 与终态事件中必须携带同一个非零 created_at, created_at 为 0 时也不得被 omitempty 省略, unmarshal→re-marshal 不丢上游值。测试实质与上游 aea725f 相同; 下游唯一改动是 CreatedAtStableAcrossEvents 夹具的 chat 分片加上 finish_reason:stop (+1 -1), 因为下游 bridge.go terminal() 在 finish_reason 缺失时会发 response.failed 而非 response.completed, 该测试仍以 response.completed 为断言目标。这一行不证明新的下游修复, 只是适配 terminal 语义, 故记为 reference。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L166): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+1 -1): L84 夹具 `{\"choices\":[{\"index\":0,\"delta\":{\"content\":\"hi\"},\"finish_reason\":\"stop\"}]}`; 断言 L95-L100 仍要求 seen 含 response.created 与 response.completed 且 created_at 相等", - "被测代码: bridge.go ensureChatToResponsesCreated L1953-L1969 / FinalizeChatCompletionsResponsesStream L1913-L1931 (CreatedAt: state.Created), ChatCompletionsResponseToResponses L1384-L1391 (resp.Created 优先否则 time.Now), anthropic_to_responses_response.go (AnthropicToResponsesResponse/FinalizeAnthropicResponsesStream, 不在本切片)", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_reasoning.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "6eca06612627d0e9e96210833ed34c02395d84563fc1de1d6efa80dc9ae4bd03", - "review_fingerprint": "6eca06612627d0e9e96210833ed34c02395d84563fc1de1d6efa80dc9ae4bd03", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增文件 (上游无此路径): ResponsesReasoning 的自定义 UnmarshalJSON/MarshalJSON/Clone/HasField。UnmarshalJSON 同时保存已知字段与全部原始成员 (map[string]json.RawMessage, 保留大整数/精度), MarshalJSON 以原始成员为底、仅覆盖被程序改动的已知字段 (原值等于新值则不动; 显式 null/空串与省略区分), Clone 深拷贝 rawFields 使转换后的请求不污染源请求, HasField 区分客户端显式给出与省略。这是协议对象保真机制, 支撑 chatcompletions_to_responses.go 的 reasoning 合并与 responses_capabilities.go 的原生判定。已核对 MarshalJSON 对已知字段原始值做字符串反序列化: 非字符串原值在 UnmarshalJSON 阶段即被 alias 解码拒绝, null 解码为空串, 因此 L36-L38 的错误分支实际不可达, 无隐患。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L89, new downstream file): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "anchors: UnmarshalJSON L8-L21 (alias 解码 + rawFields), MarshalJSON L26-L51 (knownFields 覆盖规则: present 且原值==新值→跳过; 不 present 且新值空→跳过), Clone L55-L67 (逐键 append 拷贝 RawMessage), HasField L71-L79, knownFields L81-L89 (effort/summary/mode/context/generate_summary)", - "call chain: rawFields 字段声明在 types.go 的 ResponsesReasoning; 使用方 chatcompletions_to_responses.go L67/L73, responses_capabilities.go L19, bridge.go responsesReasoningChatCompatible L50; 行为由 responses_reasoning_test.go 五个测试覆盖 (静态阅读)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_reasoning_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5198d9753644ffae6c63dc33b3ab79836ffa4e72c1fd57a29f6e5f0a7f6c5ec3", - "review_fingerprint": "5198d9753644ffae6c63dc33b3ab79836ffa4e72c1fd57a29f6e5f0a7f6c5ec3", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试 (上游无此路径), 证明 responses_reasoning.go 与 responses_capabilities.go 的下游行为: (1) RoundTrip 五组原始 JSON (含 null 成员、空串、9007199254740993 大整数、1e1000、嵌套数组) 反序列化再序列化后逐成员原文相等; (2) TypedEnvelopes 证明 ResponsesRequest/ResponsesResponse/ResponsesStreamEvent.response/ChatCompletionsRequest 四种外层都保真嵌套 reasoning 且不发明 effort; (3) CloneAndExplicitOptions 证明 nil 安全、Clone 修改不回写源对象、显式 null/空串保留、typed 改空仍输出空串; (4) DoesNotInventDefaults 证明缺省/null reasoning 不输出; (5) NativeCapability 表驱动证明 mode/context/generate_summary/未知成员触发原生要求且 ResponsesToChatCompletionsRequest 返回 Param=reasoning 的 ResponsesConversionError; (6) ChatMerge 证明 reasoning_effort 只覆盖 effort、summary 显式 null/空串不被 auto 覆盖、源请求不被污染。使用 gjson 读取原文, 断言与被测源码一致。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L197, new downstream file): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "anchors: TestResponsesReasoningConfigurationRoundTrip L11-L27, assertReasoningRawMembers L31-L38, TypedEnvelopes L40-L58, CloneAndExplicitOptions L60-L99, DoesNotInventDefaults L101-L113, NativeCapability L115-L149, ChatMerge L151-L197", - "被测代码: responses_reasoning.go 全部四个方法; responses_capabilities.go ResponsesReasoningRequiresNative L15-L25; chatcompletions_to_responses.go L65-L76; bridge.go L70-L72", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_to_anthropic.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c090cc0173ff48479dea2fcdec1da6e2ad60d92a78d098d15b4a956145edf890", - "review_fingerprint": "c090cc0173ff48479dea2fcdec1da6e2ad60d92a78d098d15b4a956145edf890", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Responses 响应/事件→Anthropic Messages 响应/SSE 的转换 (reasoning→thinking 块与 signature_delta, function_call/custom_tool_call→tool_use, web_search_call→server_tool_use 对, 文本 done/终态补发未送达文本, Read 工具 pages 空串清洗, 用量换算)。下游相对上游 aea725f 只改 encrypted_content 的处理: 三处去掉 strings.TrimSpace (非流式 L39、output_item.added L387、closeCurrentBlock L799), 密文按原字节透传不再被修剪; output_item.done 上 reasoning 项的 PendingThinkingSignature 先清空, 仅当 Status 为空或 completed 时才采用该项的 encrypted_content (L631-L637), 显式未完成的 reasoning 项不再提供可回放签名。属于核心 Anthropic 协议桥的正确性修正 (密文保真 + 状态门), 非插件业务。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L821, 2 sequential chunks): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+13 -6): L39 `item.EncryptedContent != \"\"` 取代 TrimSpace 判定; L383-L387 added 阶段保留 encrypted 前缀作兜底并去 TrimSpace; L628-L637 done 阶段 status 门 (\"\"/completed 才采用, 否则清空); L799 closeCurrentBlock 签名不再 TrimSpace", - "call chain: ResponsesEventToAnthropicEvents 分派表 L232-L270; closeCurrentBlock L791-L821 在 thinking 块关闭时发 signature_delta; 非本切片测试 responses_to_anthropic_*_test.go 覆盖 (未读取/未执行)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_to_chat_function_state.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "48e7b8e309081cf64f7b8ebf585c274929756d906c945f69675180e0611d0ba3", - "review_fingerprint": "48e7b8e309081cf64f7b8ebf585c274929756d906c945f69675180e0611d0ba3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增文件 (上游无此路径): Responses SSE→Chat chunks 方向的 function_call 快照对齐状态机。每个 output_index 只保存已下发参数的字节数与 sha256 运行哈希 (不保留全文), 后到的 output_item.added/done、function_call_arguments.done、response.completed 终态 output 等 '权威快照' 只允许补发缺失后缀: 前缀哈希不一致、完成后再变长/变短、call_id/name/item id 与已宣告值矛盾、同一 call_id 出现在两个 output_index、终态 output 缺少已宣告的调用、状态非 completed 或参数非法 JSON 时置 state.ProtocolError 并停止产出 chunk; resToChatCompleteFunctions 用 call_id/item id (而非数组位置或工具名) 把终态数组项匹配回已知 output_index。这是核心协议网关的流式一致性机制, 由 responses_to_chatcompletions.go 的 ResponsesEventToChatChunks 调用。已核对 hash.Hash.Sum(nil) 不重置状态、prefix 比较与 argumentBytes 推进顺序正确。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L160, new downstream file): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "anchors: responsesChatFunctionState L13-L20 (argumentBytes+argumentHash+argumentsDone), responseChatFunctionError L22-L24, resToChatFunctionItem L26-L98 (occupied index L38-L41, 身份矛盾 L46-L50, 跨 index 重复 call_id L51-L58, complete 校验 L71-L75), resToChatArgumentsSnapshotSuffix L100-L114, resToChatCompleteFunctions L123-L160 (identity 匹配 L137-L142, 未见已宣告调用 → error L149-L156)", - "call chain: 由同包 responses_to_chatcompletions.go 的 ResponsesEventToChatChunks/终态处理调用 (见该文件记录); ResponsesEventToChatState.functionCalls/ProtocolError/OutputIndexToToolIndex 字段定义于 responses_to_chatcompletions.go; 行为由 responses_to_chat_function_state_test.go 覆盖 (静态阅读)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_to_chat_function_state_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "686db4e56dc43ad3c72789d90efab4ed66de361118ea165b510f7925b2bbf873", - "review_fingerprint": "686db4e56dc43ad3c72789d90efab4ed66de361118ea165b510f7925b2bbf873", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试 (上游无此路径), 证明 responses_to_chat_function_state.go 的对齐规则: FunctionSnapshots 以 10 种事件序列 (added 全量/done 全量/仅终态/仅 done/部分增量+done/arguments.done 重复/空参数终态快照等) 断言累积参数恰等于最终参数、call_id 与 name 不重复不发明、index 恒为 0、role 只发一次、finish_reason=tool_calls 且无 ProtocolError; ArgumentsDoneRejectsContradictingPrefix 与 CustomInputDoneSharesPrefixState 证明 function 与 custom 两种 done 共用前缀状态且矛盾/二次尾部被拒; FunctionSnapshotRejectsContradiction 五例 (arguments/call_id/name/malformed/after_done) 置 ProtocolError 且终态不再产出 chunk; LateIdentity 证明迟到的 call_id/name 只补差量; CannotDropAnnouncedCall 证明终态 output 缺少已宣告调用即错误; 另两例证明 BufferedResponseAccumulator 用真实身份而非数组位置匹配、部分增量不填充终态参数。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L183, new downstream file): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "anchors: TestResponsesEventToChatFunctionSnapshots L9-L67 (map 驱动 10 序列), ArgumentsDoneRejectsContradictingPrefix L69-L84, CustomInputDoneSharesPrefixState L86-L106, BufferedResponseAccumulator_ArgumentDonePreservesCallIdentity L108-L126, PartialDeltaDoesNotFillTerminalArguments L128-L134, FunctionSnapshotRejectsContradiction L136-L162, LateIdentity L164-L175, CannotDropAnnouncedCall L177-L183", - "被测代码: responses_to_chat_function_state.go 全部, responses_to_chatcompletions.go ResponsesEventToChatChunks / BufferedResponseAccumulator.SupplementResponseOutput", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/responses_to_chatcompletions.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9324748a97d7a29d530d6e4d3322e7c1d5a41dd6a591a09b38d4ccaf3c447352", - "review_fingerprint": "9324748a97d7a29d530d6e4d3322e7c1d5a41dd6a591a09b38d4ccaf3c447352", - "review_status": "pending" - }, - { - "path": "backend/internal/pkg/apicompat/service_tier_passthrough_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "80402312acb4d10c9973444e5ed52dbdae80ee0ca8d9df68667c092e9beaec72", - "review_fingerprint": "80402312acb4d10c9973444e5ed52dbdae80ee0ca8d9df68667c092e9beaec72", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "service_tier 透传守卫测试: Responses→Chat 非流式/流式、Chat→Responses 非流式/流式四个方向都如实回传上游 service_tier, 缺失时不输出该字段, ResponsesResponse 反序列化保留该字段。测试实质与上游 aea725f 相同; 下游唯一改动 (+2) 是 ChatCompletionsChunkToResponsesEvents_PreservesServiceTier 在 Finalize 前显式设 state.FinishReason=stop 并写入非空 Text, 因为下游 bridge.go terminal() 对 finish_reason 缺失或空文本会发 response.failed 而非该测试查找的 response.completed。这两行只是适配 terminal 语义, 不证明新的下游修复, 记为 reference。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L177): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+2 -0): L149-L150 `state.FinishReason = \"stop\"` 与 `state.Text.WriteString(\"fixture\")`; 断言 L151-L155 仍查找 response.completed 且 ServiceTier==flex", - "被测代码: responses_to_chatcompletions.go ResponsesToChatCompletions L20-L33 / makeChatDeltaChunk L470-L484 (ServiceTier 回显), bridge.go chatServiceTier L1445-L1450 与 ensureChatToResponsesCreated L1953-L1969, terminal() L1935-L1951 (空文本无工具 → upstream_empty_response)", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/apicompat/types.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "1945f655a3c6c97fada5afba9b3da969c24ce5354f5e2a6a1cb02245762db93b", - "review_fingerprint": "1945f655a3c6c97fada5afba9b3da969c24ce5354f5e2a6a1cb02245762db93b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "apicompat 包的全部线格式类型: Anthropic Messages 请求/响应/SSE、OpenAI Responses 请求/输入项/工具/响应/事件/用量、Chat Completions 请求/消息/工具/响应/chunk, 以及 tool_search_call 自定义 Marshal/Unmarshal、ResponsesUsage 多别名归一化。下游相对上游 aea725f (+56 -28): ResponsesReasoning 扩为 Effort(改 omitempty)/Summary/Mode/Context/GenerateSummary + 私有 rawFields (自定义序列化见 responses_reasoning.go); ResponsesInputItem 新增 Summary 字段与 MarshalJSON, reasoning 输入项即使仅有签名也强制输出 summary:[] (其他类型不加该字段); ResponsesResponse 与 ChatCompletionsRequest 各新增 Reasoning *ResponsesReasoning (响应回显与 Chat 入口的 Responses 兼容扩展); AnthropicContentBlock.Signature 注释改为供应商无关措辞。均为宿主协议类型定义的通用机制。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L881, 2 sequential chunks): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f: Signature 注释 L66-L67; ResponsesReasoning L248-L259; ResponsesInputItem.Summary L278-L279 与 MarshalJSON L292-L307; ResponsesResponse.Reasoning L399; ChatCompletionsRequest.Reasoning L698", - "call chain: rawFields 由 responses_reasoning.go UnmarshalJSON/MarshalJSON/Clone/HasField 读写, ResponsesReasoningRequiresNative (responses_capabilities.go L19) 遍历; ChatCompletionsRequest.Reasoning 由 chatcompletions_to_responses.go L67 Clone; ResponsesInputItem.MarshalJSON 由 anthropic_to_responses.go / chatcompletions_to_responses.go 输出输入项时生效 (responses_reasoning_test.go TypedEnvelopes 覆盖四种外层, 静态阅读)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/httpclient/pool.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "cc5878595e7d9ecd11400b0e8ffe546c1270e6e5f2b5c45fdf00f190535ceaaf", - "review_fingerprint": "cc5878595e7d9ecd11400b0e8ffe546c1270e6e5f2b5c45fdf00f190535ceaaf", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "共享 HTTP 客户端池: 按 Options 生成缓存键复用 http.Client/Transport, 代理经 proxyurl.Parse + proxyutil.ConfigureTransportProxy 配置且失败不回退直连, 禁止 InsecureSkipVerify, 可选 validatedTransport 做 DNS Rebinding 解析 IP 校验 (30s TTL 缓存), servertiming 包装。下游相对上游 aea725f 仅新增 Options.DisableCompression (+4 -1): 透传到 Transport.DisableCompression 并纳入 buildClientKey (否则不同压缩策略会错误复用同一客户端)。生产调用方 service/account_usage_service.go L937 以 DisableCompression:true 取客户端。通用宿主基础设施, 无插件归属。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L216): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+4 -1): Options.DisableCompression L50, Transport 赋值 L125, buildClientKey 格式串增加一个 %t 并追加 opts.DisableCompression L149-L156", - "call chain (rg DisableCompression, 非测试): service/account_usage_service.go L937 (httpclient.Options 字面量); repository/http_upstream.go L1346、service/openai_ws_client.go L201/L229、plugins/codex-runtime/internal/tickets/proxy.go L100 直接设置各自 Transport, 不经本池", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/httputil/body.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3682ec6e0d4421c0751e2a22c5c5c556224e8db9a1594190bd5fbcb464a063bf", - "review_fingerprint": "3682ec6e0d4421c0751e2a22c5c5c556224e8db9a1594190bd5fbcb464a063bf", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "网关请求体读取: 按 Content-Length 预分配、透明解压 zstd/gzip/deflate (64MB 解压上限)、PrereadBody 零拷贝回填、NormalizeLenientJSONRequestBody 把 JSON 字符串内的原始控制字节转义为 \\u00XX 并去 BOM。下游相对上游 aea725f (+154 -64): 删除自研分块读取器 readRequestBodyChunks, 改为 io.Copy 进预分配 buffer 并保留读取错误; 新增 RequestBodyReadError{Stage,ReceivedBytes,DecodedBytes,Err} (只记录阶段与字节数, 不含请求内容); 传输层仅出现 io.ErrUnexpectedEOF 且已收字节经宽松规范化后为完整 JSON 时, 返回字节+错误, 由 ReadLenientJSONRequestBodyWithPrealloc 校验 json.Valid 后接受, 其他调用方仍因 err!=nil 失败关闭; 解压路径同样区分 EOF 与其他错误, 二者并存时 errors.Join 并标 stage=read_decode; 新增 isOnlyUnexpectedEOF 遍历 Unwrap()/Unwrap() []error 整条错误链, 拒绝 Join(EOF, other); readDecompressedBodyWithLimit 读 limit+1 字节并在超限时返回 http.MaxBytesError (上游用 io.LimitReader 静默截断 64MB 之后的数据再交给 JSON 解析)。是核心请求入口的正确性/安全修复, 无插件归属。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L358): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f: +RequestBodyReadError L17-L38; ReadRequestBodyWithPrealloc 改造 L110-L196 (identity 路径 EOF 恢复 L116-L137, decode 路径 L146-L185); +ReadLenientJSONRequestBodyWithPrealloc 新语义 L200-L214; +updateDecodedRequestMetadata L216-L220; +isOnlyUnexpectedEOF L225-L258; readDecompressedBodyWithLimit L276-L285 替换三处 io.ReadAll(io.LimitReader(...)); -readRequestBodyChunks", - "call chain: PrereadBody 供 multipart/多次消费路径回填 (L57-L88); 宽松读取的调用方在 handler 层 (rg ReadLenientJSONRequestBodyWithPrealloc), 行为由 body_lenient_json_test.go 十余个新用例覆盖 (静态阅读)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/httputil/body_lenient_json_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3ca2b838314b40860a1004fcb151fdcc1102df8669e76207c7202bfef7560117", - "review_fingerprint": "3ca2b838314b40860a1004fcb151fdcc1102df8669e76207c7202bfef7560117", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "宽松 JSON 请求体测试。上游部分: 字符串内 NUL/ANSI 转义为 \\u0000/\\u001b、BOM 去除、结构性无效 JSON 不被修复、httptest 端到端接受控制字符并拒绝截断 JSON、转义膨胀超限返回 MaxBytesError。下游新增 (+179) 全部针对 body.go 的 EOF/解压修复: terminalErrorReader+requestWithTerminalError 夹具 (Content-Length 比实际多 1 字节并在尾部注入错误); identity 路径 UnexpectedEOF 时返回已收字节且 RequestBodyReadError.Stage=read/ReceivedBytes 正确; 宽松读取在完整 JSON 时恢复、截断 JSON 时仍报 UnexpectedEOF、非 EOF 错误与 Join(EOF, 非 EOF) 均拒绝; readDecompressedBodyWithLimit 超限返回 MaxBytesError(limit); gzip/zstd 在传输层 EOF 后仍恢复解码 JSON 且 Content-Encoding/ContentLength 被归一化; 缺少 8 字节 footer 的 gzip 完整 JSON 可恢复, 不完整 JSON 拒绝。这些断言证明下游修复的具体行为。含一个启动本地 httptest.Server 的用例, 本次仅静态阅读未运行。", - "evidence": [ - "Full-file static review (L1-L363): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+179 -0): 夹具 L17-L31; TestReadRequestBodyWithPrealloc_preserves_identity_bytes_on_unexpected_eof L204-L223; recovers_complete_json L225-L236; rejects_truncated L238-L246; rejects_non_eof L248-L257; rejects_joined L259-L268; TestReadDecompressedBodyWithLimitRejectsExpansion L270-L276; gzip/zstd 传输 EOF 恢复 L278-L318; gzip 缺 footer 恢复 L320-L339; 不完整 gzip JSON 拒绝 L341-L363", - "被测代码: body.go ReadRequestBodyWithPrealloc L94-L196, ReadLenientJSONRequestBodyWithPrealloc L200-L214, isOnlyUnexpectedEOF L225-L258, readDecompressedBodyWithLimit L276-L285; samplePayload/newRequestWithBody 定义于同包 body_test.go L14-L26", - "Test source statically read only; not executed (the httptest server case was not run)." - ] - }, - { - "path": "backend/internal/pkg/httputil/body_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "94346a1b907d37c90d4a3e2e12819bb4fddf34b6485b65cfcabc5735708fdcb7", - "review_fingerprint": "94346a1b907d37c90d4a3e2e12819bb4fddf34b6485b65cfcabc5735708fdcb7", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "ReadRequestBodyWithPrealloc 基础用例: identity 透传、zstd/gzip/deflate 解码并清除 Content-Encoding/更新 ContentLength、不支持的 br 报错且信息含编码名、损坏 zstd 报错、nil body 返回 nil、identity 显式编码透传; 同时定义 samplePayload 与 newRequestWithBody 供 body_lenient_json_test.go 复用。下游相对上游 aea725f 仅在 RejectsUnsupportedEncoding 的 t.Fatal 后加一行 return (+1), 用于静态分析器的 nil 流判定, 不改变任何断言, 故为 reference。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L144): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+1 -0): L106 `return` 紧随 t.Fatal(\"expected error for unsupported encoding, got nil\")", - "被测代码: body.go ReadRequestBodyWithPrealloc / decompressRequestBody L260-L285 / updateDecodedRequestMetadata L216-L220", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/openai/constants.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "7e98e36f83e4e17b1b7824a15e45c93d3e9a0355fcbe73e06feabc56c628817c", - "review_fingerprint": "7e98e36f83e4e17b1b7824a15e45c93d3e9a0355fcbe73e06feabc56c628817c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 模型目录与 Codex 提示词常量: DefaultModels 17 项 (gpt-5.6 系/gpt-6/gpt-5.5/5.4/5.3-codex-spark/codex-auto-review/gpt-image 系)、DefaultTestModel、CodexUsageProbeModel, go:embed 的 GPT-5-Codex/5.1/5.2/5.5/6-Astra base instructions, CanonicalizeOpenAIModelAliasSpelling 拼写规范化与 CodexBaseInstructionsForModel 按模型选 prompt (含空 prompt 回退链)。下游相对上游 aea725f 仅扩展 Model 结构体 (+12 -6): 新增 Description/ContextWindow/MaxInputTokens/MaxOutputTokens/ReasoningEfforts/DefaultReasoningEffort 六个 omitempty 字段, 让 /v1/models 与管理端账号测试模型列表能携带能力元数据; 其中 ReasoningEfforts/DefaultReasoningEffort 由 handler/admin/account_handler.go L2837 (service.AccountTestReasoningOptions) 与 handler/gateway_handler.go L1506 填充。模型容量/能力数据本身在 service/model_context_capacity*.go 与 plugins/model-policy/catalog, 本文件只是宿主协议 DTO, 不含插件业务规则。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L165): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+12 -6): 仅 Model 结构体 L10-L23 新增六个 omitempty 字段; DefaultModels/instructions/CanonicalizeOpenAIModelAliasSpelling/CodexBaseInstructionsForModel 与上游一致", - "call chain (rg openai.Model, 非测试): handler/gateway_handler.go L1217/L1506-L1580 (/v1/models 组装), handler/admin/account_handler.go L2831-L2871 (账号测试模型列表, L2837 填 ReasoningEfforts/DefaultReasoningEffort), service/account_test_service.go L193-L240; 未在宿主中发现直接为 openai.Model 字面量设置 ContextWindow/MaxInputTokens 的代码 (容量走 service.ModelContextCapacity 类型)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/openai_compat/upstream_capability.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "dfda6871881bccd64d65be5cb2e66221d98162041eee5e9f35664e6d869345f6", - "review_fingerprint": "dfda6871881bccd64d65be5cb2e66221d98162041eee5e9f35664e6d869345f6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI APIKey 账号的上游能力判定: accounts.extra 中的 openai_responses_supported 探测标记与 openai_responses_mode 手动覆盖 (auto/force_responses/force_chat_completions) 决定入站 chat 请求是否走 CC→Responses 转换, 未探测时按 '现状即证据' 默认走 Responses。下游相对上游 aea725f 新增 (+47) 账号级 reasoning.summary 兼容契约: ExtraKeyReasoningSummaryMode=openai_reasoning_summary_mode, ReasoningSummaryMode passthrough/auto/omit, ParseReasoningSummaryMode 校验, ResolveReasoningSummaryMode(extra, official) 缺失或非法时官方 OpenAI 默认 passthrough、其它兼容目的地默认 auto。消费方为 service/openai_gateway_request_body.go L80 (以 isOfficialOpenAIModelsBaseURL 判定 official) 与 L94 (omit 分支删除字段)。属于宿主 OpenAI 协议网关的账号能力机制, 不含插件业务。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L162): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+47 -0): ExtraKeyReasoningSummaryMode L61-L65, ReasoningSummaryMode 常量 L68-L79, ParseReasoningSummaryMode L83-L90, ResolveReasoningSummaryMode L94-L107", - "call chain (rg, 非测试): service/openai_gateway_request_body.go L80 ResolveReasoningSummaryMode(account.Extra, isOfficialOpenAIModelsBaseURL(targetURL)), L94 case ReasoningSummaryModeOmit; 既有 ShouldUseResponsesAPI/ResolveResponsesSupport 与上游一致; 测试见 upstream_capability_test.go (静态阅读)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/openai_compat/upstream_capability_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bbe8972114dcff648dc031d3698bfa14c6c3ad4d876b76b5d8a3f9c44705a792", - "review_fingerprint": "bbe8972114dcff648dc031d3698bfa14c6c3ad4d876b76b5d8a3f9c44705a792", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "openai_compat 能力判定的表驱动测试。上游部分: ResolveResponsesSupport 14 例 (nil/缺键/类型错误→Unknown, 探测 bool, force 模式覆盖探测), ShouldUseResponsesAPI 7 例 (关键不变量: 未探测返回 true), NormalizeResponsesSupportMode 5 例。下游新增 (+53): TestResolveReasoningSummaryMode 10 例证明官方默认 passthrough、兼容目的地默认 auto、显式 passthrough/auto/omit 生效、非法值与错误类型回退目的地默认; TestParseReasoningSummaryMode 5 例证明只接受三个合法值。断言与 upstream_capability.go L83-L107 的实现逐条对应, 证明下游新增契约的行为。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L141): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+53 -0): TestResolveReasoningSummaryMode L90-L116, TestParseReasoningSummaryMode L118-L141", - "被测代码: upstream_capability.go ParseReasoningSummaryMode L83-L90, ResolveReasoningSummaryMode L94-L107; 既有测试对应 ResolveResponsesSupport L128-L155 / ShouldUseResponsesAPI L160-L162 / NormalizeResponsesSupportMode L111-L120", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/proxyurl/parse_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9ece7be14079b3d816fc65d94cd9b8ffca7a84fcaad12eda3c3cfb2c6ea4f4e3", - "review_fingerprint": "9ece7be14079b3d816fc65d94cd9b8ffca7a84fcaad12eda3c3cfb2c6ea4f4e3", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "proxyurl.Parse 的测试: 空/空白直连, http/https 有效代理, socks5 自动升级 socks5h (含大小写与带认证), 无效 URL/缺 host/不支持 scheme 的错误信息, 含密码 URL 报错时脱敏, 空白裁剪, IPv6, socks5h 保持, 无 scheme 裸地址报错。下游相对上游 aea725f 仅在 5 处 t.Fatal 后追加 return (+5), 供静态分析的 nil 流判定, 不改变任何断言, 故为 reference。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L220): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+5 -0): L44, L79, L90, L101, L131 各加一行 return 于 t.Fatal 之后", - "被测代码: internal/pkg/proxyurl Parse (不在本切片); 与 httpclient/pool.go L135 及 proxyutil 的调用方约定一致 (socks5→socks5h 升级防 DNS 泄漏)", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/pkg/proxyutil/dialer.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d9af9e5e627817b890935743ecd0b1a1fa13ceee3d681c1032d34f2d2b279810", - "review_fingerprint": "d9af9e5e627817b890935743ecd0b1a1fa13ceee3d681c1032d34f2d2b279810", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "统一的 Transport 代理配置入口 ConfigureTransportProxy (http/https 走 Transport.Proxy, socks5/socks5h 走 DialContext)。下游相对上游 aea725f (+4 -38): 原本内联的 scheme 分派、proxy.FromURL、ContextDialer 优先/回退包装逻辑整体迁到插件 SDK 包 github.com/Wei-Shaw/sub2api/pkg/extensionapi/proxy (下游新增, git ls-tree aea725f 无该目录) 的 Configure(transport, url, forward), 本文件只保留带 10s 建连超时/30s keepalive 的 socks5ForwardDialer (常量改引用 SDK 的 SOCKSDialTimeout/SOCKSKeepAlive) 并一行委托。目的是让插件与宿主共用同一份代理配置实现; 本文件仍是宿主通用基础设施 (调用方 httpclient/pool.go L141, repository/http_upstream.go L1371/L1457, pkg/antigravity/client.go L276, pkg/websearch/manager.go L420, service/vertex_service_account.go L212), SDK 包本体属另一切片 (core-extension-and-job-host)。SDK import 被放进标准库分组属格式瑕疵, 不影响行为。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L52): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+4 -38): import 改为 proxytransport SDK 包 L13; 常量 L20-L24 改引用 proxytransport.SOCKSDialTimeout/SOCKSKeepAlive; ConfigureTransportProxy L50-L52 委托 proxytransport.Configure(transport, proxyURL, socks5ForwardDialer), 删除原 scheme switch/FromURL/ContextDialer 回退", - "call chain: backend/pkg/extensionapi/proxy/transport.go L16-L19 (SOCKSDialTimeout=10s, SOCKSKeepAlive=30s, func Configure; forward 为 nil 时 L32 自建带超时 dialer); 调用方 rg 见 reason; 上游 aea725f 不存在 backend/pkg/extensionapi/proxy", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/tlsfingerprint/dialer.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "036064712536de46ef2026421a6f9ac81dd910f2f758478dee8e956a27f058cd", - "review_fingerprint": "036064712536de46ef2026421a6f9ac81dd910f2f758478dee8e956a27f058cd", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "uTLS 指纹拨号器 (模拟 Node.js 24.x/Claude Code 的 ClientHello: 17 套密码、3 组曲线、9 种签名算法、14 项扩展顺序、GREASE/ECH 处理), 提供直连/HTTP CONNECT 代理/SOCKS5 代理三种 DialTLSContext。下游相对上游 aea725f (+78 -6) 全部是建连阶段的超时与取消修复: 新增 connectTimeout/handshakeTimeout=10s 与 newTCPDialer (10s 建连 + 30s keepalive) 取代零值 net.Dialer 和 proxy.Direct (后者在代理不可达时会卡到内核 TCP 重传耗尽); setupDeadline 用 context.AfterFunc 把 ctx 取消映射为 conn.SetDeadline(now), 使 HTTP CONNECT 的写请求/读响应也受 ctx 约束, 成功后清除 deadline 并停止回调; SOCKS5 路径改用 proxy.ContextDialer.DialContext(connectCtx) 而非无 ctx 的 Dial; 三条路径的 TCP 建连都套 connectTimeout, performTLSHandshake 套 handshakeTimeout; CONNECT 写/读失败时若 connectCtx 已结束则以 ctx.Err() 作为返回错误; 失败路径统一 finish()+Close 防泄漏。是上游请求转发传输层的正确性修复 (无界阻塞→可取消), 无插件归属。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L538, 2 sequential chunks): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f: +常量与 newTCPDialer L20-L26, +setupDeadline L30-L52; NewDialer 默认 baseDialer 改 newTCPDialer L160; SOCKS5 forward 改 newTCPDialer L199, ContextDialer+connectCtx L207-L213; HTTP 代理建连 connectCtx L242-L244, setupDeadline/finish/defer L250-L262, 写/读失败映射 ctx.Err L284-L286/L296-L298, finish 成功路径 L310-L315; 直连 connectCtx L326-L328; performTLSHandshake handshakeTimeout L343-L344", - "call chain: DialTLSContext 供 http.Transport.DialTLSContext 使用 (调用方在 repository/service 层, 不在本切片); 行为由同包 dialer_deadline_test.go (本地监听器/管道) 覆盖, 静态阅读", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/pkg/tlsfingerprint/dialer_deadline_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c92525ba2c801a2ef945764f882d952c68c821713ba35f15020bbc8d6ed94b65", - "review_fingerprint": "c92525ba2c801a2ef945764f882d952c68c821713ba35f15020bbc8d6ed94b65", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试 (上游无此路径), 证明 dialer.go 的超时/取消修复: TestFingerprintDefaultDialDeadline 断言 newTCPDialer 为 10s/30s 且自定义 baseDialer 收到不超过 connectTimeout 的 deadline、取消错误原样透出; TestFingerprintStalledSetupCancellation 对 direct/http/socks5 三种模式 × 是否主动 cancel 六个子用例, 用只接受不响应的本地 127.0.0.1 监听器模拟卡死的对端, 断言 200ms ctx 内 (上限 2s) 返回错误、不产出连接且对端 goroutine 结束 (socket 不泄漏); TestFingerprintSetupDeadlineCleared 用 net.Pipe 证明 finish() 后再 cancel 不会毒化可复用 socket; TestFingerprintHandshakeAndProxyReuse 在子进程 (GODEBUG=x509usefallbackroots=1, SetFallbackRoots 只信任测试证书) 中对 httptest TLS 服务经直连/内置 HTTP CONNECT 代理/内置 SOCKS5 代理各完成两次请求, 证明握手与连接复用且 Proxy-Authorization 不泄漏到源站。全部只用本机监听, 无外网; 本次仅静态阅读, 未运行。", - "evidence": [ - "Full-file static review (L1-L255, new downstream file): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "anchors: TestFingerprintDefaultDialDeadline L22-L38, TestFingerprintStalledSetupCancellation L40-L96, TestFingerprintSetupDeadlineCleared L98-L114, TestFingerprintHandshakeAndProxyReuse L118-L165 (子进程重入 L119-L126), fingerprintTestProxy L167-L255 (最小 HTTP CONNECT 与 SOCKS5 代理实现)", - "被测代码: dialer.go newTCPDialer L24-L26, setupDeadline L30-L52, 三个 DialTLSContext L182-L336, performTLSHandshake L340-L370", - "Test source statically read only; not executed (no local listener or subprocess was started)." - ] - }, - { - "path": "backend/internal/pkg/tlsfingerprint/dialer_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3902a13cfd406e8013837137ceee1268276551f0e8a5a393a5c5872c138589d9", - "review_fingerprint": "3902a13cfd406e8013837137ceee1268276551f0e8a5a393a5c5872c138589d9", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "带 //go:build unit 标签的指纹拨号器测试: 外网用例 (google.com 连通、tls.peet.ws JA3/JA4 校验、多 profile 指纹) 由 skipNetworkTest 在 short 模式或未设 TLSFINGERPRINT_NETWORK_TESTS=1 时跳过; 本地用例校验 GREASE profile 扩展更多、代理拨号器构造、ClientHelloSpec 默认/自定义密码套件、曲线转换。下游相对上游 aea725f 仅在两处 t.Fatal 后追加 return (+2), 不改变断言, 故为 reference。静态阅读, 未执行, 未访问任何外网。", - "evidence": [ - "Full-file static review (L1-L412): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+2 -0): L205 与 L229 各加一行 return 于 t.Fatal(\"expected dialer to be created\") 之后", - "被测代码: dialer.go NewDialer/NewHTTPProxyDialer/NewSOCKS5ProxyDialer L157-L175, buildClientHelloSpecFromProfile L406-L529, toUTLSCurves L373-L379; 外网期望值 JA3 44f88fca027f27bab4bb08d4af15f23e 对应 L98-L105 注释", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/repository/account_create_fence_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e58e8a8ae4ac701ee3564e876576bb13e2c451881ba4c1dce5e818dcea3f93f8", - "review_fingerprint": "e58e8a8ae4ac701ee3564e876576bb13e2c451881ba4c1dce5e818dcea3f93f8", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "全文129行:真实Ent事务调用生产lockAccountCreatePolicy,错误配置/定义及任一99%绑定在持久化前拒绝;有效事务阻挡另一连接配置UPDATE并实际断言55P03。生产AccountRepository.Create只在同事务内可见,rollback后无账号;合成plugin状态按fixture身份清理。已有本地专用PG执行记录通过,parent只读不重跑;未启动HTTP或插件进程。", - "evidence": [ - "artifacts/evidence/v027-account-create-integration-review.json#verification", - "artifacts/evidence/v027-astra-account-create-backend-review.json" - ] - }, - { - "path": "backend/internal/repository/account_credential_identity_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "4b0c0dd7ddc8d6f01ac1bd1eb12376aab199bb53062c3a904f92b664d3534ec8", - "review_fingerprint": "4b0c0dd7ddc8d6f01ac1bd1eb12376aab199bb53062c3a904f92b664d3534ec8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增文件(上游 ls-tree 无此路径):account_credential_identities 表的原生 SQL 仓储。Bind 用 Serializable 事务包裹 BindInTransaction;后者先 pg_advisory_xact_lock(hashtext(fingerprint)) 串行化同指纹绑定,再按 account_id+active FOR UPDATE 读当前身份:同指纹幂等返回、ExpectedGeneration 不符报 GenerationConflict、他账号 active 同指纹报 ErrCredentialIdentityConflict,轮换时先 retire 旧行再以 generation+1 插入,23505 统一译为冲突错误。Cindy 专属限制(仅 cindy_laxa_v1/apikey/固定 base_url)由 service.ValidateAccountCredentialIdentityBinding 持有,仓储本身是中性的身份持久化机制,故归 core 数据层。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "L21-L41 Bind: BeginTx(LevelSerializable)+defer Rollback; L54 advisory xact lock on fingerprint; L58 active row FOR UPDATE scoped by account_id; L75-L83 cross-account active fingerprint FOR UPDATE -> ErrCredentialIdentityConflict; L85-L116 generation = active.Generation+1 or COALESCE(MAX)+1; L118-L127 INSERT ... RETURNING, 23505 translated at L197-L203.", - "Identity scoping verified against backend/migrations/230_account_credential_identities.sql: unique partial index (account_id) WHERE active, plain fingerprint index (historical duplicates allowed by design); FindByFingerprint L146-L159 enforces 64-hex lowercase before querying.", - "Callers traced: backend/internal/repository/account_job_cindy_mutation.go L100 (BindInTransaction inside ent tx, account row pre-locked by lockCindyAccountJobTarget), backend/internal/service/cindy_health.go L172/L201 (GetActiveByAccountID); business validation stays in service/account_credential_identity.go L69-L104, not in this repo.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_credential_identity_repo_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e715887c209bcab09c2dd3f44f727aedb3cdbf617ea0eeb4c8293ca954533836", - "review_fingerprint": "e715887c209bcab09c2dd3f44f727aedb3cdbf617ea0eeb4c8293ca954533836", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "下游新增 sqlmock 单元测试:断言首绑生成 generation=1、同指纹重放在历史查询前幂等短路、换钥匙轮换将旧行 UPDATE 置 retire 并以 generation+1 INSERT、他账号 active 同指纹返回 ErrCredentialIdentityConflict 且回滚、他账号已 retire 的指纹不阻塞新账号建史。仅静态阅读理解其断言,未执行;不证明上游行为的修复,故记 reference。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "TestAccountCredentialIdentityBindCreatesGenerationOne L70-L89; ...RerunIsIdempotentBeforeHistoricalFingerprintLookup L91-L107 (expects commit right after the account-scoped FOR UPDATE read, no fingerprint-owner query); ...RotationIncrementsGeneration L109-L128 (UPDATE id=13 then INSERT gen 5); ...RejectsAnotherAccountFingerprint L130-L147 (ExpectRollback); ...IgnoresAnotherAccountsRetiredFingerprintAndCreatesNewHistory L149-L167.", - "Subject is the core credential-identity persistence mechanism; fixtures use service.AccountCredentialFingerprint with ProviderProfileCindyLaxaV1 (L14-L28), matching the service-side validation contract.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_edit_fence_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "441729a5286726744d55d864feedda214b4b22bc1eeb3a31e19b56e2f7e02840", - "review_fingerprint": "441729a5286726744d55d864feedda214b4b22bc1eeb3a31e19b56e2f7e02840", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_extra_revision.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2bf8e5ec7572b1bd710ec99273f32bba1e6b6da0267689111b3aba9849d6fdc4", - "review_fingerprint": "2bf8e5ec7572b1bd710ec99273f32bba1e6b6da0267689111b3aba9849d6fdc4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增文件:UpdateExtraIfRevision 以 accounts.updated_at 为版本号做 CAS——事务内 FOR NO KEY UPDATE 锁行读 updated_at,与期望不符返回 (false,nil) 放弃写入,相符则经 dbent.NewTxContext 复用 UpdateExtra 的保护字段/outbox/缓存路径,提交后同步单账号调度快照。用于给异步元数据结果(codex 身份回填)挡旧写,属通用乐观并发持久化原语。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "L13-L51: tx + FOR NO KEY UPDATE row lock on accounts.updated_at (deleted_at IS NULL), current.Equal(expected) gate at L40, delegation to r.UpdateExtra via dbent.NewTxContext at L43, syncSchedulerAccountSnapshot only after commit at L49.", - "Single non-test caller traced: backend/internal/service/openai_codex_client_identity.go L203 (accountExtraRevisionWriter interface) and L306 (backfill passes account.UpdatedAt as the fence); rows closed on every branch L23-L39.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_extra_revision_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8f8a32558935c2fa64305e9a18b199efabed3db2d0e51ecb6543ed5b284dbe9c", - "review_fingerprint": "8f8a32558935c2fa64305e9a18b199efabed3db2d0e51ecb6543ed5b284dbe9c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "下游新增集成测试(//go:build integration):先用原 updated_at 成功 CAS 写 extra,再带外 UPDATE 推进 updated_at 后用旧时间戳重试,断言 applied=false 且较新的 fixture_metadata=newer 与 operator_note=keep 均未被覆盖。依赖 integration_harness_test.go 的真实 PostgreSQL(SUB2API_TEST_POSTGRES_ONLY_DSN 或 testcontainers 容器)。本次仅静态阅读断言内容,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "L15-L39: mustCreateAccount fixture, first UpdateExtraIfRevision applied=true (L28-L30), out-of-band UPDATE ... updated_at=clock_timestamp() (L31), stale retry applied=false (L33-L35), final SELECT proves newer value and untouched operator_note (L36-L39).", - "DSN guard verified in backend/internal/repository/integration_harness_test.go L47-L66: TestMain uses SUB2API_TEST_POSTGRES_ONLY_DSN when set, otherwise testcontainers postgres:18.1 with Docker availability check (skips locally, fails loudly in CI).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_job_cindy_mutation.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "24b6a4c972a77e1045f3e8611211e36c8fa4e7454b077c66ec84c6c6ab709485", - "review_fingerprint": "24b6a4c972a77e1045f3e8611211e36c8fa4e7454b077c66ec84c6c6ab709485", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_job_cindy_mutation_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e936a48f4f1f350e80447b578ae9dd65ff7f339aebaf8815056a5badf29ce57a", - "review_fingerprint": "e936a48f4f1f350e80447b578ae9dd65ff7f339aebaf8815056a5badf29ce57a", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_job_plugin_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ddcbac4a107623799bf742152ec20a5ddf66d60b86da91c06b4f92fce0462c27", - "review_fingerprint": "ddcbac4a107623799bf742152ec20a5ddf66d60b86da91c06b4f92fce0462c27", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Fully inspected persistent job owner/generation stamping, target shared host-task lease retaining the promotion barrier, rejection of late/stale submissions, and cancellation of preexisting target jobs. No case was rerun; repository job-create and execution bind call sites were separately traced.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Source inspection is not represented as an executed test." - ] - }, - { - "path": "backend/internal/repository/account_job_repo.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "fa813066452e2905dd81974f1f0ce69798ee8b829a9520d33de55b03002c4444", - "review_fingerprint": "fa813066452e2905dd81974f1f0ce69798ee8b829a9520d33de55b03002c4444", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_job_repo_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "196a8e413de0ff9fee522a0f68ccff63c4af35d1efae7abd48bffd063428dc22", - "review_fingerprint": "196a8e413de0ff9fee522a0f68ccff63c4af35d1efae7abd48bffd063428dc22", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "下游新增 sqlmock 单元测试(//go:build unit):断言 Create 单事务内先插 job 再插 items、250 个 item 拆成 3 条 ≤100 的批量 INSERT、CompleteItems 仅按实际迁移行数累计且重放(0 行)不再 UPDATE job、ResultAccountIDs 的 succeeded 投影、MarkInterrupted 两条 UPDATE、Claim 的 SQL 含全局<2 与同管理员同 kind 限制及 SKIP LOCKED、Reserve 上限钳到 AccountJobBatchSize、Prune 严格小于截止时间并直接读 232 迁移文本断言 FK 级联。静态阅读断言,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "TestAccountJobRepositoryCreatePersistsJobAndItemsAtomically L49-L73; ...BulkInsertUsesBoundedStatements L75-L88 (3 ExpectExec for 250 seeds); ...CompletionCountsOnlyTransitions L90-L113 (second run: zero-row updates, no job UPDATE expected); ...ClaimEnforcesGlobalAndAdminKindLimits L138-L151 (regex over CTE SQL); ...ReserveCapsBatchAtOneHundred L153-L165; ...PruneOnlyFinishedBeforeCutoff L167-L182 reads migrations.FS 232 file for the ON DELETE CASCADE line.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_plugin_projection.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "aaf475107e5176f4bbf8f9bdf44dff31146570bc0b4049c23970ef7f4a6cd95f", - "review_fingerprint": "aaf475107e5176f4bbf8f9bdf44dff31146570bc0b4049c23970ef7f4a6cd95f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "下游新增文件:两个纯函数保护 extra 里插件投影键 plugin_account_projections——withoutPluginAccountProjection 把该键从任何入站写剥掉,preservePluginAccountProjection 在整账号覆盖写时把数据库当前投影值搬回合并结果。被 account_repo.go 的 Create/UpdateExtra/BulkUpdate/lockAndMergeAccountProbeExtra 调用,保证管理员编辑不能伪造或误删插件投影,投影只能走扩展宿主自己的写路径。键名与结构定义在 service/plugin_scheduling.go,对所有插件通用,无单域业务规则。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "L8-L15 withoutPluginAccountProjection (maps.Clone before delete, no mutation of caller map); L17-L27 preservePluginAccountProjection copies current[PluginAccountProjectionKey] over sanitized incoming.", - "Call sites traced in account_repo.go: L162 (createAccountRecord SetExtra), L741 (lockAndMergeAccountProbeExtra merge), L2835 (UpdateExtra), L3191 (BulkUpdate); key constant service.PluginAccountProjectionKey = plugin_account_projections at backend/internal/service/plugin_scheduling.go L11, consumed by PluginManager.SchedulingDecision.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_quota_estimate.go", - "candidate_owner": "core-quota-and-protocol", - "role": "source", - "present": true, - "content_sha256": "ab3e6fa117a3b06a06583eea6126747c67b39eceed5ed4cb60ec607d0de28dc7", - "review_fingerprint": "ab3e6fa117a3b06a06583eea6126747c67b39eceed5ed4cb60ec607d0de28dc7", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "SQL persistence keeps one estimate row per account, identity, and period; the upsert preserves the earliest baseline, rejects older observations, and exposes base/latest values for delta estimation. A first settled post-import observation naturally inserts the baseline, so import-time SQL is not required.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=ab3e6fa117a3b06a06583eea6126747c67b39eceed5ed4cb60ec607d0de28dc7; current_sha256=ab3e6fa117a3b06a06583eea6126747c67b39eceed5ed4cb60ec607d0de28dc7; inventory_sha256_match=true", - "lines 11-15: QuotaCostPoint uses usage_logs cursor/count and account_stats_cost fallback", - "lines 18-26: account_quota_estimates upsert resets baseline on cost/utilization rollback and rejects older observed_at", - "lines 30-40: ReadQuotaEstimate returns baseline/latest or nil on no row", - "callers: backend/internal/service/quota_estimate.go:74-135" - ] - }, - { - "path": "backend/internal/repository/account_quota_estimate_integration_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ae474d71453a7759b69c12fd831816f05daea1f1ba70133bf400edec4952a1d9", - "review_fingerprint": "ae474d71453a7759b69c12fd831816f05daea1f1ba70133bf400edec4952a1d9", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static test source covers baseline persistence, late observation rejection, insufficient data after cost shrink, and identity miss; tests were not rerun in this audit.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=ae474d71453a7759b69c12fd831816f05daea1f1ba70133bf400edec4952a1d9; current_sha256=ae474d71453a7759b69c12fd831816f05daea1f1ba70133bf400edec4952a1d9; inventory_sha256_match=true", - "TestQuotaEstimateRepositoryPersistsBaselineAndRejectsLateObservations", - "TestQuotaEstimateRepositoryRecalibratesAfterCostHistoryShrinks", - "assertions at lines 33-55 preserve older baseline/latest and reject an older observation" - ] - }, - { - "path": "backend/internal/repository/account_quota_snapshot_order_integration_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f37ccb79d0f615aacb71f1d1627df57c5cad5eb4f31edf040e183c8755857d6c", - "review_fingerprint": "f37ccb79d0f615aacb71f1d1627df57c5cad5eb4f31edf040e183c8755857d6c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static integration test source covers legacy window normalization and locked update ordering; tests were not rerun in this audit.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=f37ccb79d0f615aacb71f1d1627df57c5cad5eb4f31edf040e183c8755857d6c; current_sha256=f37ccb79d0f615aacb71f1d1627df57c5cad5eb4f31edf040e183c8755857d6c; inventory_sha256_match=true", - "TestQuotaSnapshotOrderingAndLegacyWindowClock", - "lines 39-66: older locked writer cannot overwrite a newer committed observation", - "backend/internal/service/account_quota_windows.go:103-127" - ] - }, - { - "path": "backend/internal/repository/account_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c3676fb7588dc65166fe21563f7225072bbb99920b3f6d6f7aae69a2bd395f8a", - "review_fingerprint": "c3676fb7588dc65166fe21563f7225072bbb99920b3f6d6f7aae69a2bd395f8a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "账号仓储主文件(4220 行全文精读;相对上游 aea725f 变更 +706/-267)。下游改动集中在通用持久化机制:1) 全面支持 dbent.TxFromContext——Create/GetByID/GetByIDs/Delete/BindGroups/SetSchedulable/UpdateExtra/BulkUpdate 及 loadProxies/loadAccountGroups 在调用方事务内复用 tx client,outbox 随事务原子写入且失败改为返回错误(不再仅记日志);2) 新持久字段 wire_platform/provider_profile/management_folder_id 与 Cindy 列(balance_insufficient/banned/credential_generation)进出实体映射;3) lockAndMergeAccountProbeExtra 扩展为行锁下合并 model context capacities/overrides/metadata(mergeAccountModelContextExtra 按模型级 patch 合成)、保留 codex 门票(MergeOpenAICodexTicketExtra,坏 extra 降级不阻断编辑)与插件投影,并检测凭证代际变化以清 Cindy 终态列;4) UpdateExtra 对 codex_usage_updated_at 快照实施单调守卫(CTE MATERIALIZED+FOR NO KEY UPDATE+RFC3339 正则,旧快照记日志忽略),门票键列入调度中性前缀;5) SetRateLimited 委托 SetRateLimitedIfLater 变为单调写,新增 ClearTempUnschedulableIfMatch 原值 CAS 清除(outbox 同语句写入);6) 所有可调度查询(ent 与原生 SQL)叠加 cindyTerminalStateAvailablePredicate,UpdateCredentials/BulkUpdate 凭证变化时同语句清 Cindy 终态,Delete 级联清 cindy_health_states 并 retire 凭证身份;7) pq.Array 移除改用 pgx 原生数组。Cindy 终态语义与 ClassifyStrictCindyGroup 标记是 Cindy 域规则驻留 core 仓储,但按协调约定 Cindy 主体保留在 core(cindy-provider 插件目录无同规则副本,插件侧 catalog/management.go 仅做管理 UI 视图分类),不构成二执行器。发现一处低危跨层不一致(见 findings:ops 负载投影改用裸 Concurrency 而调度器仍用 EffectiveLoadFactor)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Tx propagation & atomic outbox: L130-L147 Create, L974-L1030 Delete (also DELETE cindy_health_states L1007, retire account_credential_identities L1010-L1015), L1991-L2043 BindGroups, L2767-L2791 SetSchedulable, L2834-L2971 UpdateExtra (monotonic CTE L2883-L2931, neutral-key snapshot sync L2962-L2969), L3186-L3411 BulkUpdate (cindy terminal-state CASE L3265-L3271, shouldSync on credentials L3399).", - "Row-locked merge: lockAndMergeAccountProbeExtra L623-L827 (14-column SELECT ... FOR NO KEY UPDATE incl. credential-generation predicate L644-L646 and COALESCE(extra) L667; ticket preservation fallback comment L727-L739); mergeAccountModelContextExtra L833-L874; scheduler-neutral ticket prefixes L54-L69.", - "Cindy availability predicate L2076-L2081 applied at L1051, L2088, L2147 (raw SQL), L2196, L2231, L2252, L2277, L2329, L3436; monotonic rate limit L2345-L2385; ClearTempUnschedulableIfMatch L2637-L2662; pgx arrays L1406/L1505/L2153/L3338 (pq import removed).", - "Finding cross-check: ListSchedulableAccountLoads L2053-L2072 selects only id+concurrency and returns MaxConcurrency=Concurrency, while service/openai_account_scheduler.go L1548/L1728 and service/openai_gateway_scheduling.go L1340 still use EffectiveLoadFactor(); sole consumer of the projection is service/ops_metrics_collector.go L43/L421.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_cindy_balance.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "5181352930c00ba15e4d4c07a79e62cc1aee7565e55d2197afad7c1398276b31", - "review_fingerprint": "5181352930c00ba15e4d4c07a79e62cc1aee7565e55d2197afad7c1398276b31", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_repo_cindy_balance_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "090c215fc44d2976b1fe331be6e5d2fe7382337d45ba9a9223c861b672d00732", - "review_fingerprint": "090c215fc44d2976b1fe331be6e5d2fe7382337d45ba9a9223c861b672d00732", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_repo_cindy_balance_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3c394f3f5f6801096eddc5d9c1703340c8f3a3612fb5b20530871001dba2e872", - "review_fingerprint": "3c394f3f5f6801096eddc5d9c1703340c8f3a3612fb5b20530871001dba2e872", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_repo_cindy_group_identity_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c08c25625119f5d02b5e3b1b6396514e2e7f513606c67703e405867672e315de", - "review_fingerprint": "c08c25625119f5d02b5e3b1b6396514e2e7f513606c67703e405867672e315de", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_repo_cindy_group_identity_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2e2460a8dc942bf9bebb407178605c635226525988ddeed4a27270d8cc83583f", - "review_fingerprint": "2e2460a8dc942bf9bebb407178605c635226525988ddeed4a27270d8cc83583f", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_repo_cindy_identity_lifecycle_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a4b9be912962295f12ea26d3ce5dda634b6e96fd6c5423baade48074df833338", - "review_fingerprint": "a4b9be912962295f12ea26d3ce5dda634b6e96fd6c5423baade48074df833338", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/account_repo_codex_fingerprint_seed_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6cae147332c4bc25bce4b6c76cad0c80f55c66f400c001a525818d75ea8c5649", - "review_fingerprint": "6cae147332c4bc25bce4b6c76cad0c80f55c66f400c001a525818d75ea8c5649", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "上游已有的 sqlmock 单测,下游仅做 pgx 驱动迁移适配:sqlmock.New 增加 ValueConverterOption(pgxSQLMockValueConverter{})(pgx_sqlmock_test.go 定义,放行非 []byte 切片参数),期望参数从 lib/pq 的字符串数组 {27,28} 改为原生 []int64{27,28},与 account_repo.go 移除 pq.Array 对应。断言内容不变:BulkUpdate/UpdateExtra 在启用 codex_fingerprint_mode 时用每行 SQL(jsonb_set+gen_random_uuid,仅 openai/oauth)补种子、剥离客户端提供的种子值、UPDATE 或 outbox 失败时整事务回滚。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Diff vs aea725f: only 4 sqlmock.New(...) calls gain pgxSQLMockValueConverter and two WithArgs change from string-array to []int64{27,28} (L46, L72, L80, L98, L106); converter defined at backend/internal/repository/pgx_sqlmock_test.go L10-L18.", - "Assertions read: TestBulkUpdateEnsuresCodexFingerprintSeedWithPerRowSQL L18-L43 (client seed stripped from payload, per-row CASE SQL with canonical pattern), TestUpdateExtraEnsuresCodexFingerprintSeedAtomicallyWhenEnabling L45-L69, rollback tests L71-L123 (update failure and outbox failure both roll back).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_codex_lifecycle.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0396d77f77abc164316ba75b6946299ad7ef6e3bf199b571b4a8691be52243cf", - "review_fingerprint": "0396d77f77abc164316ba75b6946299ad7ef6e3bf199b571b4a8691be52243cf", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "下游新增文件:两枚只读 DTO 映射助手——scanTicketState 按固定列序扫描旧表 openai_codex_ticket_runtime 为 service.CodexTicketLifecycle,ticketFromAccount 从 extra[codex_turn_ticket:模型] 反序列化 CodexTicketRecord(State 为空即弃)。唯一调用方是 plugin_legacy_import.go 的一次性割接导入,把遗留 codex 门票状态搬进 codex-runtime 插件;文件本身不做生命周期决策,属宿主侧桥接旧表示的胶水,归 adapter/codex-runtime。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "L10 ticketStateColumns fixed column list; L12-L36 scanTicketState NullTime/json handling (L33 best-effort Unmarshal of last_result); L38-L51 ticketFromAccount extra-key parse with State empty-string rejection.", - "Only callers: backend/internal/repository/plugin_legacy_import.go L83 (SELECT ticketStateColumns FROM openai_codex_ticket_runtime) and L87; that importer is documented as a one-time representation adapter (its L20-L21 comment), lifecycle decisions run in the plugin after cutover.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_codex_ticket_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e3555d09b445d86f1db2a379b2c79e87266c6f33cbb6c649f855c50de53fc15a", - "review_fingerprint": "e3555d09b445d86f1db2a379b2c79e87266c6f33cbb6c649f855c50de53fc15a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "三条 sqlmock/纯函数测试,证明账号仓储在管理端编辑路径上对服务端托管的门票键(codex_turn_ticket:* / codex_ticket_runtime:*)的保护:lockAndMergeAccountProbeExtra 在 FOR NO KEY UPDATE 行锁下读回 current extra,经 service.MergeOpenAICodexTicketExtra 丢弃编辑方提交的所有门票键、只保留库内最新门票,其余管理键以提交为准;current extra 为非对象 JSON 时不使整个账号编辑失败、仅放弃保留且仍剥离伪造键;门票键为调度中性,单独更新不触发调度 outbox,但与真实调度字段混批时仍触发。被测对象是宿主仓储的数据完整性机制(account_repo.go L63-L64、L623-L741、L3142-L3170),而非 codex-runtime 的采集/续期业务;插件当前把票据存于扩展状态(plugins/ 内无 codex_turn_ticket 引用),该规则保护的是遗留/残留账号 extra 键。上游无此文件。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S62-codex-ticket-T1-review.json", - "L14-L32 TestLockAndMergeAccountExtraPreservesLatestCodexTicket:mock 期待 `SELECT.*FOR NO KEY UPDATE` 且参数为 (41, openai, oauth, credentials, nil),current_extra 含 codex_turn_ticket:model=latest;断言合并后该键取库内值、编辑方的 codex_turn_ticket:injected 与库内旧管理键 old_admin_setting 均不存在、new_admin_setting 保留。对应 account_repo.go L740 MergeOpenAICodexTicketExtra(openai_codex_ticket.go L89-L105:先删提交侧全部 IsOpenAICodexTicketExtraKey 键再复制库内同类键)。", - "L36-L53 TestLockAndMergeAccountExtraDegradesOnUnparsableExtra:current_extra=[1,2,3] 时 require.NoError 且 injected 键仍被剥离,对应 account_repo.go L731-L738 的降级分支(仅记录 id 与 err,不打印 extra 内容)。L55-L66 TestCodexTicketExtraIsSchedulerNeutral:isSchedulerNeutralExtraKey 对前缀 codex_turn_ticket: 为真(schedulerNeutralExtraKeyPrefixes L63),shouldEnqueueSchedulerOutboxForExtraUpdates 单门票键为假、混入 openai_passthrough 为真(L3142-L3170)。", - "归属说明:rg --no-config -uu 显示 codex_turn_ticket 在 plugins/ 仅出现于 account-tools 文案;backend 内唯一读者为 repository/account_repo_codex_lifecycle.go L38-L50 ticketFromAccount(遗留态读取),无生产写入者,故测试守护的是宿主仓储对遗留门票键的防篡改机制。不宣称:测试未被执行,sqlmock 仅静态阅读;未验证真实 Postgres 行锁行为。" - ] - }, - { - "path": "backend/internal/repository/account_repo_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c1b704935cd1b48e86bfa30791896179cab03f250530ad7deaba11e1d0814d3b", - "review_fingerprint": "c1b704935cd1b48e86bfa30791896179cab03f250530ad7deaba11e1d0814d3b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "账号仓储集成测试套件(1924 行全读,//go:build integration,经 testEntTx/testEntClient 使用真实 PostgreSQL——TestMain 优先 SUB2API_TEST_POSTGRES_ONLY_DSN,否则 testcontainers)。下游相对上游 +194 行,新增断言直接证明本片下游修复/行为变更:TestCindyMarkerResetsOnlyWhenAccountIdentityChanges 验证 Update/UpdateCredentials/BulkUpdate 仅在 platform/type/credentials 实际变化时清 cindy 终态列、无关编辑保留;TestSetRateLimitedDoesNotShortenReset 与 ...IfLater... 证明限流窗口单调不回缩;TestUpdateExtra_StaleCodexSnapshotCannotOverwriteNewerWindowState 证明 codex_usage_updated_at 旧快照被忽略;OAuth 刷新分页测试断言 paused(schedulable=false)账号仍是刷新候选。其余为上游既有 CRUD/过滤/分组/Grok CAS 断言。仅静态阅读,未执行任何测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Real-DB harness: SetupTest L139-L144 uses testEntTx; TestDelete_RemovesSchedulerAccountSnapshot L272-L298 and TestGrokOAuthConditionalMutationRollsBackWhenOutboxInsertFails L1513-L1550 use testEntClient/integrationDB directly (DSN guard integration_harness_test.go L47-L66).", - "Downstream-delta assertions: TestCindyMarkerResetsOnlyWhenAccountIdentityChanges L875-L957 (marker cleared on platform/type/credentials change, kept on rename/no-op credential rewrite, across Update/UpdateCredentials/BulkUpdate incl. cache snapshot); monotonic rate limit L992-L1023; stale codex snapshot ignored L1680-L1702; paused account included in ListOAuthRefreshCandidatePage L325-L415.", - "Atomicity proofs read statically: failAtomicSchedulerOutboxSQLExecutor L82-L92 nulls event_type so the single-statement CTE mutation rolls back (L1513-L1550); cancelAfterAtomicMutationSQLExecutor L94-L105 proves detached bounded snapshot sync (L1481-L1511).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_model_availability_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "371928d6a575d8ddd3f4750ef112b3c275a581eb49356d2d4b273ab2d9d7d0e5", - "review_fingerprint": "371928d6a575d8ddd3f4750ef112b3c275a581eb49356d2d4b273ab2d9d7d0e5", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "上游已有的 sqlmock SQL 形状单测,下游 +2 行:在 ListModelAvailabilityCandidates 的分组查询 WHERE 子句断言中加入 cindy_balance_insufficient_at 与 cindy_banned_at,证明模型可用性诊断查询也带上了下游新增的 Cindy 终态可用性谓词;同时保留上游断言(配置态谓词存在、瞬态谓词 rate_limit/overload/temp_unschedulable/expires 不出现)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Diff vs aea725f adds exactly L49-L50 (require.Contains cindy_balance_insufficient_at / cindy_banned_at); captured SQL comes from captureEntQueryMatcher over repo.ListModelAvailabilityCandidates with groupID=42, platform anthropic, includeGrouped=false (L18-L40).", - "Matches account_repo.go L2318-L2343 (group path delegates to queryAccountsByGroup with schedulable+ignoreTransientState, which appends cindyTerminalStateAvailablePredicate at L3433-L3437).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_model_context_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8bbe221b9d713611ae6a12e62f17972114508f719e1587aa2c26703ca5f6bbbc", - "review_fingerprint": "8bbe221b9d713611ae6a12e62f17972114508f719e1587aa2c26703ca5f6bbbc", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "下游新增单元测试(307 行,sqlmock+纯函数):覆盖 mergeAccountModelContextExtra 的全部合并语义——行锁下的最新 capacities/overrides/metadata 覆盖调用方过期快照且不改调用方 map、NULL/nil 不复活已删除值、按模型独立 patch 合成(set/新增/删除/空 patch/删除不存在模型/删空后移除整键)、非法 patch(0/负数/超安全整数/空模型名)与受保护账号(openai oauth、cindy laxa)带 patch 被拒、存储 JSON 畸形报错;并验证 lockAndMergeAccountProbeExtra 使用锁下值、三个 model context 键都会触发 outbox、Update 仅在提交成功后清 ModelContextOverridesPatch、UpdateExtra 同步写保持原子 outbox。测试的是 core 仓储的模型上下文持久化合并(plugins/ 目录无此规则副本)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "TestMergeAccountModelContextExtraPreservesLatestManagedValues L29-L59 (caller snapshot immutability asserted via before/after JSON equality); ...DoesNotResurrectRemovedValues L61-L72; ...PatchesLatestModelsIndependently L74-L127 (7 table cases); ...RejectsInvalidPatch L129-L143; ...RevalidatesProtectedAccounts L145-L159; ...RejectsMalformedStoredJSON L161-L170.", - "TestLockAndMergeAccountProbeExtraUsesLockedModelContextValues L172-L204 (14-column FOR NO KEY UPDATE row shape matches account_repo.go L638-L671); TestUpdateAccountModelContextPatchClearsOnlyAfterSuccessfulWrite L218-L268 (patch kept on outbox rollback, cleared on commit, matching account_repo.go L504); TestUpdateExtraModelContextSyncKeepsAtomicWriteAndOutbox L270-L307.", - "Ownership check: rg over plugins/ finds no model_context_overrides/upstream_model_context_capacities handling; validation lives in backend/internal/service/model_context_capacity.go L375 and model_context_identity.go L89 (core).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_ollama_cloud_usage.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "1c7d06e6bb17b4a7ec2d0232485417dc06792f273ec01821a0918666b13fcd59", - "review_fingerprint": "1c7d06e6bb17b4a7ec2d0232485417dc06792f273ec01821a0918666b13fcd59", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Ollama Cloud 用量会话/快照的组级持久化(566 行全读)。同一 api_key 在白名单平台(openai/anthropic/kimi/zhipu/deepseek/minimax,SQL 常量与 service 判定互为镜像)+ apikey + 官方 ollama.com base_url 的所有账号构成一组:写入前 FOR NO KEY UPDATE 锁全组并做锚点身份 CAS(账号 platform/type/credentials/proxy 全等)与可选期望状态 CAS,UPDATE 受影响行数必须等于组成员数否则报 ErrOllamaCloudUsageIdentityChanged;ListDue 在 SQL 内实现 debounce/max-wait/失败退避与按 key 去重(row_number PARTITION),时间戳解析对 >6 位小数截断并把 Z 改写成 +00:00(PG≤16 的 jsonpath datetime 限制),非法值 fail-open。下游相对上游仅 2 处 pq.Array 移除改用 pgx 原生数组,其余与上游一致;属 core 用量/计费探测持久化机制,无插件持有同规则。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Diff vs aea725f: only lib/pq import removal and two pq.Array call sites (L66, L252) now pass native slices; everything else byte-identical to upstream.", - "Group CAS: lockOllamaCloudUsageGroup L283-L334 (FOR NO KEY UPDATE over whole key group, anchor predicate id=$2 AND platform/type/credentials/proxy), updateOllamaCloudUsageGroup L172-L281 (expected-state canonical-JSON compare L207-L232, affected==len(members) guard L256-L262, proxy identity FOR SHARE via lockAndMatchProbeProxyIdentity L189-L195).", - "Due listing: ListDueOllamaCloudUsageAccounts L407-L566 (CTE eligible/group_activity/parsed MATERIALIZED/timed/candidates/ranked, LIMIT after due filter, group MAX(last_used_at) stamped back L556-L562); RFC3339 parse hardening ollamaCloudUsageParseRFC3339SQL L360-L393 with PG16 Z-designator note.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_ollama_cloud_usage_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "92d9cd3eb70717581e8fe96637009e626896b874da3a8b102a243b89db23f168", - "review_fingerprint": "92d9cd3eb70717581e8fe96637009e626896b874da3a8b102a243b89db23f168", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Ollama 用量仓储的真实 PostgreSQL 集成测试(733 行全读,//go:build integration,testEntTx/testEntClient + testcontainers 或 SUB2API_TEST_POSTGRES_ONLY_DSN)。断言:due 排序/限量/代理水合、三种亚秒精度与时区拼写的时间戳都不落入 fail-open(附 PG15 最老版本运行说明)、组 MAX(last_used_at) 取自兄弟账号、非法日期 fail-open 不炸整查询、组写入跨平台与 URL 变体原子生效且换钥匙后旧锚点 CAS 拒绝、并发 Save/Delete 串行化后整组状态一致(真库 goroutine 竞争)、CN 兼容平台纳入组与 due、无变化凭证不清托管键、代理身份变更使快照失效并拒绝在飞 CAS、SQL due 规则与 service 纯函数一致且 21 个未到期组不会饿死真正到期组。下游 delta 仅 2 行适配 lockAndMergeAccountProbeExtra 的三返回值签名。仅静态阅读,未执行任何测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Diff vs aea725f: exactly two call sites gain the discarded second return (L232, L424); all assertions otherwise unchanged.", - "Key behaviors read: precision matrix L94-L148 (asserting absence proves parse success), group-max/fail-open L150-L219, atomic group writes + stale-anchor rejection L239-L304, real concurrency serialization via integrationDB L306-L377, CN platform extension L390-L447, proxy-identity invalidation L530-L572, SQL due rules vs service semantics + starvation guard L631-L733.", - "Real-DSN guard confirmed via integration_harness_test.go TestMain (SUB2API_TEST_POSTGRES_ONLY_DSN or testcontainers postgres, Docker check).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_ollama_cloud_usage_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "44850f678feaf64a32513880264c2fbf75856bd2a4f70f817ad8ca9d7675b21a", - "review_fingerprint": "44850f678feaf64a32513880264c2fbf75856bd2a4f70f817ad8ca9d7675b21a", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Ollama 用量仓储的 sqlmock 单元测试(382 行全读)。断言:RowsAffected=0 即身份冲突并回滚、代理身份变化拒写、会话密文只作为绑定参数绝不出现在 SQL 文本、base_url SQL 正则与 service.IsOllamaCloudUsageAccount 语义逐例一致(含 evil.test 反例)、组查询单条严格批量 SQL、due 查询的全部谓词与窗口/去重/排序子句、BulkUpdate 的 Ollama 清理按值条件化、UpdateCredentials 身份变化清三个托管键且清理分支必须带顶层 credentials DISTINCT 守卫、平台白名单常量与 service 判定互为镜像(防两侧漂移)、普通 CN apikey 账号清理语义等价。下游 delta 仅 4 处 sqlmock.New 增加 pgxSQLMockValueConverter 适配 pgx 数组参数。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Diff vs aea725f: only ValueConverterOption(pgxSQLMockValueConverter{}) added at L22, L110, L162, L190; assertions unchanged.", - "Read anchors: ciphertext-out-of-SQL L104-L141, regex/service semantic table L143-L159, strict batch query L161-L187, due SQL clause list incl. Z-rewrite regexp L189-L238, value-conditional bulk cleanup L240-L259, top-level DISTINCT guard L300-L318, whitelist mirror L323-L341, semantic equivalence L346-L382.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_schedulable_projection_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "55103c62ad452ff1dfd193eb6d59da5235131f66b28de0fc5ada28fc1136ac9b", - "review_fingerprint": "55103c62ad452ff1dfd193eb6d59da5235131f66b28de0fc5ada28fc1136ac9b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "上游已有的集成测试(//go:build integration,真实 PostgreSQL),验证 ListSchedulableAccountLoads 与 ListSchedulable 返回同一账号集合与顺序、瞬态排除(disabled/unschedulable/expired/overloaded/rate-limited/temp-blocked 排除,past 窗口与 auto_pause=false 保留)。下游 delta 把期望负载从 EffectiveLoadFactor() 改为裸 Concurrency:load_factor=9/concurrency=2 的账号期望 2(原 9),concurrency=0 期望 0(原 1),证明该行为变更是刻意的(与 findings[0] 记录的跨层不一致相关)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Diff vs aea725f: L77 wantByID uses accounts[i].Concurrency (was EffectiveLoadFactor()), L98 expects 2 for positiveLoad (was 9), L100 expects 0 for zeroFallback (was 1).", - "Fixtures L27-L66 build positiveLoad(concurrency=2,load_factor=9), concurrencyFallback(4), zeroFallback(0,0) plus six excluded/included transient-state accounts; ordering assertion L96 checks priority order 10/20/30.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_schedulable_projection_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "df3fb1a473f68afa8448ee1e1e63f56a2b04aac45338cdd3a36a97e4ec18396f", - "review_fingerprint": "df3fb1a473f68afa8448ee1e1e63f56a2b04aac45338cdd3a36a97e4ec18396f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "上游已有的 sqlmock 投影单测,下游改动两处:1) 新增 TestEveryAccountRepositoryTerminalAvailabilityPredicateExcludesBanned——读 account_repo.go 源文本,断言 cindyTerminalStateAvailablePredicate() 至少出现 9 次、ent 谓词只定义一次、balance 与 banned 计数成对、原生 SQL 内联谓词成对,且 group_repo.go 的 groupAccountAvailableSQL 也含同一 Cindy 终态谓词——用源码扫描守卫所有可调度查询不漏 Cindy 终态过滤;2) 投影断言从三列(id,concurrency,load_factor)改为两列(id,concurrency)且 MaxConcurrency=Concurrency,WHERE 谓词列清单加入两个 cindy 列,证明 findings[0] 所记行为变更是刻意的。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "New source-scan guard L23-L40 (os.ReadFile account_repo.go; >=9 predicate call sites, paired CindyBalanceInsufficientAtIsNil/CindyBannedAtIsNil counts, raw-SQL pair counts, groupAccountAvailableSQL containment — that constant lives at backend/internal/repository/group_repo.go L985-L991).", - "Projection assertions L50-L104: exactly one query, two selected columns, load_factor absent (L78-L81), predicate columns include cindy_balance_insufficient_at/cindy_banned_at (L95-L96), ORDER BY priority preserved (L101-L103).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_temp_unsched_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e7d48d4798e71a13b7238920db4d9661dbfb866ac67aeb8fc4780517a61a246d", - "review_fingerprint": "e7d48d4798e71a13b7238920db4d9661dbfb866ac67aeb8fc4780517a61a246d", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "临时停调/Grok 条件突变/OAuth 刷新候选 SQL 的 sqlmock 单测(410 行全读)。下游 delta:新增 TestAccountRepository_ClearTempUnschedulableIfMatch_NoRowsAffectedDoesNotWriteOutbox,证明下游新增的原值 CAS 清除把 UPDATE 与 outbox INSERT 收在同一条 CTE 语句、未命中时返回 (false,nil) 且不单独 enqueue(参数序也被钉死);其余为 pgx 适配(ValueConverter、平台参数从 pq 字符串数组改 []string 直取)。既有断言覆盖:SetTempUnschedulable 零行不写 outbox、Grok 条件突变 SQL 的资格谓词与原子 outbox、调用方取消后 outbox 仍随语句提交、OAuth 刷新候选 SQL 的 IS NOT TRUE 三值逻辑守卫与 paused 账号保留、对账模式排除 apikey。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Diff vs aea725f: new test L28-L39 (single statement, args [42, \"\", until, event] asserted); pgx adaptations at L277, L326-L328, L333; driver.Valuer unwrap removed.", - "Matches account_repo.go ClearTempUnschedulableIfMatch L2637-L2662 (CTE UPDATE+INSERT scheduler_outbox, COALESCE(reason,'')=$2, until=$3 exact match).", - "Existing coverage read: Grok conditional mutations L53-L148 (atomic outbox, cancellation), reconciliation vs background CAS distinction L150-L222, OAuth refresh page SQL shape L276-L357 (paused accounts kept, 3-valued-logic guard comments).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_repo_upstream_billing_probe_update_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f5096df96c6140071ae962a367e0cc8b5c406d42a01d7feae3092ff98f4bfd8f", - "review_fingerprint": "f5096df96c6140071ae962a367e0cc8b5c406d42a01d7feae3092ff98f4bfd8f", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "上游计费探测合并/开关语义与原子 outbox 回滚的 sqlmock 单测(483 行全读,上游已有)。下游 delta 全部是对本片仓储机制扩展的适配:lockAndMergeAccountProbeExtra 锁行 SELECT 从 9 列扩到 14 列(新增 credential_generation_unchanged、三个 model context 列、current_extra)并改用三返回值;两处 sqlmock 增加 pgx ValueConverter、ANY 参数改 []int64;updatedAccountRows 夹具补 wire_platform/provider_profile/management_folder 与 Cindy 列。断言实质未变:数据库当前快照优先于过期输入、身份变化清快照、显式停探测清快照并单向拉低 rate_sync(绝不由 sync 反推 probe)、Ollama 托管键防伪造、probe 资格不匹配整批回滚、UpdateExtra/UpdateCredentials/BulkUpdate/UpdateWithAccountBillingSettings 在 outbox 失败时全部回滚。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Diff vs aea725f: row-shape columns extended at L84, L175, L214, L374 (14 columns incl. credential_generation_unchanged and current_extra), 3-value call sites L94/L184/L226, pgx adaptations L318/L327/L453/L462, updatedAccountRows fixture L475-L483 gains WirePlatformOpenAI/provider_profile and Cindy/管理列。", - "Semantics read: current-snapshot precedence table L20-L105, probe->rate_sync one-way rule L111-L201 (comment L111-L114), Ollama managed-field protection L203-L240, eligibility mismatch rollback L317-L339, outbox rollback quartet L364-L473.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_taxonomy_integration_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5a04b27fb8c2dcc268ba2d73527301ec9b1d71fd58e095d30be24d18d3a8c9f2", - "review_fingerprint": "5a04b27fb8c2dcc268ba2d73527301ec9b1d71fd58e095d30be24d18d3a8c9f2", - "review_status": "reviewed", - "decision": "reference", - "owner": "account-tools", - "reason": "账号分类(文件夹/标签)栈的集成测试(559 行全读,//go:build integration,testEntClient+integrationDB 真实 PostgreSQL,前缀清理)。断言:ent 关系与级联(folder 置空、tag 绑定随删)、调度/共享仓储路径不水合管理分类(GetByID 返回 folder ID 但不带实体,Update 不清 folder——部分账号值无法表达 nil 语义)、CRUD 去重(normalized 名冲突 409)、软删账号的 folder 引用随删清理、并发删 folder 与指派的串行化终态、控制台组合过滤与分面计数(含 uncategorized 与 direct 代理桶)、批量分类的 ExpectedMatchCount CAS(409 后无部分生效)与非法 tag 整体回滚、分类操作绝不改动路由分组绑定。归属:分类命名/排序/批量的策略规则在 account-tools 插件(manifest operations taxonomy.*,policy/module.go),core 的 admin_account_taxonomy.go 经 accountToolsOperation 调插件后仅做持久化,无二执行器;本测试构造 AdminService 时插件依赖为 nil,即只覆盖宿主持久化路径,不证明插件准入。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "Read anchors: migration/relations + non-hydration + partial-update semantics L70-L132, CRUD/dup/hydration L134-L212, soft-deleted reference cleanup incl. 409 ACCOUNT_FOLDER_NOT_EMPTY L214-L271, concurrent delete-vs-assign L273-L307, combined filters/facets L309-L405, bulk update CAS + rollback + routing-group isolation L407-L532.", - "Ownership traced: plugins/account-tools/manifest.source.json operations list (taxonomy.name/order/bulk/assignment/delete) and policy/module.go Invoke; core service backend/internal/service/admin_account_taxonomy.go calls accountToolsOperation at L195/L332/L420/L613 before persisting — host executes, plugin decides; test harness (L39-L64) wires NewAdminService with nil plugin deps so plugin admission is out of scope here.", - "Real-DSN guard: integration_harness_test.go TestMain (SUB2API_TEST_POSTGRES_ONLY_DSN or testcontainers).", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_traffic_observe_cache.go", - "candidate_owner": "admin-observability", - "role": "source", - "present": true, - "content_sha256": "b0a8492e1c26b9445a21b2861cf826fabd0fb142eb6395c1b6cfe8e2d04f8b33", - "review_fingerprint": "b0a8492e1c26b9445a21b2861cf826fabd0fb142eb6395c1b6cfe8e2d04f8b33", - "review_status": "reviewed", - "decision": "adapter", - "owner": "admin-observability", - "reason": "下游新增文件:账号级流量遥测(只观察)的 Redis 缓存。Begin 用单个 Lua 脚本原子完成 started 自增、60s 滚动窗口 ZSET 维护(先按 score 裁旧再 ZADD,成员含序号防同毫秒去重)、对并发槽位两个 ZSET 只读 ZCOUNT 采样(边界与 acquireScript 一致,绝不写并发键)、peak_in_flight 单调抬升与 24h TTL 刷新;Finish 走 TxPipeline HINCRBY+EXPIRE;Snapshot 用 Redis TIME 避免多实例时钟偏差,pipeline 读两协议 HASH 与窗口计数。协议与结果枚举写前校验(封闭集合),键按账号+协议有界,TTL 兜底防泄漏。状态类型即 extensionv1.AccountTrafficCounters——宿主采集、经扩展 API 供 admin-observability 插件消费,自身不含业务判定,归 adapter/admin-observability。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S06-repo-account-1-review.json", - "L40-L70 Begin Lua script (ZREMRANGEBYSCORE window trim L57, member nowMs:seq L58, read-only ZCOUNT sampling with acquireScript-consistent bounds L61, monotonic peak L62-L65, EXPIRE both keys); L110-L126 Begin validates protocol against closed enum; L129-L145 Finish validates outcome enum, TxPipeline HINCRBY+EXPIRE.", - "L148-L177 Snapshot: redis TIME clock source, exclusive '(' lower bound L156, redis.Nil tolerated; L179-L198 parse with zero defaults; keys bounded per account+protocol with 24h TTL (service.AccountTrafficObserveTTLSeconds).", - "Boundary traced: backend/internal/service/account_traffic_observe.go L103 aliases the state to extensionv1.AccountTrafficCounters and L106-L126 defines the consuming observer; slot key helpers accountSlotKey/liveAccountSlotKey shared with the concurrency cache, sampled read-only per the file-head comment L26-L29.", - "Static read only; no test execution, build, database or network access." - ] - }, - { - "path": "backend/internal/repository/account_view_atomic_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7b0f2f9951f8b87666deab025931b6d2a9b798c4f043657f6b05abe3021d6561", - "review_fingerprint": "7b0f2f9951f8b87666deab025931b6d2a9b798c4f043657f6b05abe3021d6561", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "全文复核281行真实PG fixture:三方法调用生产有序fence、scoped terminal和Resume CAS helper;pg_stat_activity等待/NOWAIT/55P03证明两owner实际锁,故障触发器只命中合成item且检查health/marker/item/outbox整体回滚;一次成功仅一份outbox,JSONB CAS保留原冻结IDs/operation key/digests并拒旧expected。固定本地专用库,cleanup仅合成行/函数,3方法实测通过;不是sqlmock、整应用或多主机证明。", - "evidence": [ - "artifacts/evidence/v027-account-view-integration-review.json#verification", - "Current complete fixture read; actual targeted results reused without rerunning." - ] - }, - { - "path": "backend/internal/repository/account_view_fence_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0ab50e15e3b13b71690ea3210e71637a746e728df18c7580e6cf705d291ea3a9", - "review_fingerprint": "0ab50e15e3b13b71690ea3210e71637a746e728df18c7580e6cf705d291ea3a9", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/affiliate_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e42c6397b19b553643be36e916dc3b43e44f3e095418e3e0fad9338ff2fcc0f7", - "review_fingerprint": "e42c6397b19b553643be36e916dc3b43e44f3e095418e3e0fad9338ff2fcc0f7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "邀请返利(affiliate)持久层:user_affiliates/user_affiliate_ledger 的绑定、累计、冻结解冻、转余额与管理端列表查询。下游相对上游 aea725f 仅做 lib/pq 到 pgx/v5 的驱动迁移:isAffiliateUniqueViolation 改用 pgconn.PgError 判定 23505,BatchSetUserRebateRate 直接传 []int64 给 ANY($2)(pgx stdlib 原生支持切片绑定)。转余额用 FOR UPDATE + CTE 原子清零并写快照台账,事务边界经 withTx 复用外层 tx。业务规则与上游一致,属宿主通用持久机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: import pq->pgconn (L15), isAffiliateUniqueViolation pgconn.PgError code 23505 (L972-L978), BatchSetUserRebateRate drops pq.Array (L1098-L1102).", - "TransferQuotaToBalance L235-L342: FOR UPDATE claim + cleared CTE + ledger snapshot in one withTx transaction; ThawFrozenQuota moves matured frozen amounts monotonically (GREATEST(...,0) L226).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/api_key_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "4de7cf923fdf4e020338fea540fd6467bad02ecbb8369f3d70dd1407c85353a8", - "review_fingerprint": "4de7cf923fdf4e020338fea540fd6467bad02ecbb8369f3d70dd1407c85353a8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "API Key 持久层。下游相对上游新增 purpose/lease_id 字段:userVisibleQuery 让 purpose='user' 之外的租约钥匙(release_acceptance,扩展宿主验收作业用)对用户 CRUD/列表/计数/分组迁移全部隐身,而 GetByKeyForAuth 仍按 activeQuery 放行认证并回带 purpose/lease_id;认证投影补选 group 的 wire_platform/provider_profile 并在 platform=cindy 时调 classifyStrictCindyGroupWithSQL 打 StrictCindy 标记(规则本体在 cindy_group_identity.go,不在本文件);另移除 pq.Array(latestUsageLogIPsQuery 直接传 []int64)。属宿主认证与数据机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: userVisibleQuery L44-L46 applied to GetByID/GetKeyAndOwnerID/list/count/search/ClearGroupIDByGroupID/UpdateGroupIDByUserAndGroup/ListKeysBy* (L87,L107,L461,L623-L634,L642,L653,L719,L741-L766,L770,L775,L786); Create sets purpose/lease (L59-L65).", - "GetByKeyForAuth L139-L268: auth projection adds FieldPurpose/FieldLeaseID/WirePlatform/ProviderProfile and StrictCindy classification for cindy-platform groups (L255-L267); classifier body lives in cindy_group_identity.go (outside slice).", - "pgx migration: latestUsageLogIPsQuery passes []int64 directly for ANY unnest (L587-L601).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/api_key_repo_cindy_group_materialization_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "38f3ad05d9f0010d76295948bc6bddc0877180336b13b5cad77ff1fe65e3eb14", - "review_fingerprint": "38f3ad05d9f0010d76295948bc6bddc0877180336b13b5cad77ff1fe65e3eb14", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "API Key 认证路径 GetByKeyForAuth 物化 Cindy 分组身份(Group.StrictCindyKnown/StrictCindy)的 SQLite 单测,上游无此文件。五个用例分别证明:全 Cindy 成员分组判定为 strict、成员 base_url 改为 openai 后变为 ordinary、已禁用但未删除的 ordinary 成员仍参与判定使分组为 mixed、空分组标记为 known-ordinary、非 Cindy 平台分组通过 sqlmock 证明完全不执行 account_groups 聚合、分类器查询失败时认证 fail-closed 返回错误且 key 为 nil。被测主体是宿主仓储 api_key_repo.go L255-L266 与 cindy_group_identity.go 的 classifyStrictCindyGroupWithSQL;plugins/ 下不存在 StrictCindy 身份判定,不构成第二执行器,属于宿主为 Cindy 域提供的认证快照数据适配。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S53-cindy-rest-T3-review.json", - "L15-L25 failingCindyClassifierExecutor 仅对含 'from account_groups' 的查询注入错误,L195-L217 用它证明 GetByKeyForAuth 对分类失败 ErrorIs 且返回 nil(fail-closed)。", - "L27-L84 strict→ordinary 翻转依赖 Account.credentials.base_url;L86-L139 显式断言 disabled 非删除成员计入 strict 判定;L166-L193 用 sqlmock 替换 repo.sql 证明 Gemini 分组不触发 Cindy 聚合。", - "调用链:api_key_repo.go GetByKeyForAuth L255-L266 → cindy_group_identity.go classifyStrictCindyGroupWithSQL(本切片文件 11);account_repo.go L1325 也复用同一分类器。rg 'StrictCindy' 在 plugins/ 下无命中。", - "文件相对上游 aea725f 为全新文件(git ls-tree 为空),整文件即下游增量。未执行测试,不宣称用例通过。" - ] - }, - { - "path": "backend/internal/repository/api_key_repo_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d4f0e0474757fcd9cae7baaf7aeeb128fa46c0337d839931c498af176ee1bcd7", - "review_fingerprint": "d4f0e0474757fcd9cae7baaf7aeeb128fa46c0337d839931c498af176ee1bcd7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "API Key 仓储集成测试(//go:build integration,经 fixtures 的 testEntTx/testEntClient 接真库)。下游相对上游只新增 TestReleaseAcceptanceKeyIsHiddenButAuthenticates:断言 purpose=release_acceptance 的租约钥匙创建后 GetByID 返回 ErrAPIKeyNotFound、ListByUserID 为空,但 GetByKeyForAuth 仍认证成功且回带 purpose 与 lease_id——证明 userVisibleQuery 隐身机制与认证路径的分离。其余为上游既有 CRUD/配额原子递增/软删墓碑断言。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Downstream delta = single new test L89-L125 asserting hidden-but-authenticates for release_acceptance lease keys.", - "DSN guard lives in fixtures_integration_test.go (testEntTx/testEntClient/integrationDB), reviewed separately in this slice; suite runs inside per-test rolled-back tx except TestIncrementQuotaUsed_Concurrent which writes real rows with cleanup (L545-L595).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/audit_log_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "1e6a875e81e0c6f43db953682d39132dd7d5ff23754796fab4e7f2f1df6599c3", - "review_fingerprint": "1e6a875e81e0c6f43db953682d39132dd7d5ff23754796fab4e7f2f1df6599c3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "审计日志仓储(raw SQL,append-only,无单条删除)。下游相对上游把 BatchInsert 从 lib/pq 的 COPY(pq.CopyIn+prepared stmt+手工事务)换成 postgresBatchInsert 单条多行 INSERT(pgx 兼容、原子、受 65535 绑定参数上限保护,helper 在 postgres_batch_insert.go,不在本切片)。语义变化:失败时不再有部分插入计数,整批原子成败。查询/清理逻辑与上游一致。宿主审计机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: pq.CopyIn transaction block replaced by auditLogInsertColumnNames + postgresBatchInsert call (L29-L33, L66-L82).", - "DeleteBefore batches deletes 5000/batch via CTE (L304-L320); TruncateAll gated at service layer by 2FA per file comment L14-L15; List caps pageSize at 200 and strips request_body (L224-L254).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/auth_cache_invalidation_cindy_identity_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8301ab83eb033072b139ab20668d6af466aa9eb9dd3a7f9d576280c408323680", - "review_fingerprint": "8301ab83eb033072b139ab20668d6af466aa9eb9dd3a7f9d576280c408323680", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "PostgreSQL 集成测试(//go:build integration),直接用原生 SQL 写 account_groups/accounts,再统计 auth_cache_invalidation_outbox 中该 API Key 的 cache_key 行数,证明迁移 212_codexrip_materialize_cindy_group_identity.sql 新增的三个触发器语义:成员插入、credentials 变更、status 变更、成员迁出旧分组、成员删除都必须入队失效;priority-only 更新与 schedulable 翻转不得入队。被测主体是数据库触发器(宿主认证缓存 outbox 机制向账号身份列与分组成员关系的扩展),测试用的分组平台是 OpenAI 而非 Cindy,说明触发器与平台无关,因此归属 core-data-and-migrations 而非候选的 cindy-provider;Cindy 身份只是其动机。仅静态阅读,未执行任何数据库操作。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S53-cindy-rest-T3-review.json", - "L47-L58 以 sha256(key) 作为 cache_key 查询 outbox(与 api_key_cache.go apiKeyAuthCacheKey 一致);L74-L121 七步写操作与期望计数 1/0/0/1/1/1/1。", - "对应触发器:migrations/212 L59-L61 trg_accounts_cindy_identity_auth_cache_invalidation AFTER UPDATE OF platform,type,credentials,status,deleted_at(故 schedulable 不触发),L75-L84 account_groups 触发器在 group_id 未变时提前返回(故 priority-only 不触发),L95-L97 AFTER INSERT OR UPDATE OR DELETE ON account_groups。", - "L104-L115 成员迁移只断言旧分组 key 入队,随后迁回并 clear,不对 otherGroup 断言;L61-L72 Cleanup 以原生 SQL 逐表删除测试数据。", - "相对上游 aea725f 为全新文件;未执行测试,不宣称触发器在生产库中已部署或用例通过。" - ] - }, - { - "path": "backend/internal/repository/batch_image_repo_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "31227ef6dc05400c589320e0ee8c9f1ac673a17104b49368fda9fdb9ceb56443", - "review_fingerprint": "31227ef6dc05400c589320e0ee8c9f1ac673a17104b49368fda9fdb9ceb56443", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "批量生图作业仓储集成测试。下游相对上游仅一处:MarkBatchImageJobSettled 的 settled_at 断言从 require.Equal 换成 time.Equal 瞬时比较,适配 pgx 返回的时区/单调钟表示差异。断言覆盖:BatchID 幂等冲突、非法 provider、状态机版本递增与事件写入、终态不可回退、item custom_id 作用域唯一(SAVEPOINT 验证)、仅 indexing 态允许重建 items、结算幂等与 settlement_completed 事件、结算失败重试计数。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Downstream delta = one assertion L287: require.True(now.Equal(*job.SettledAt)) replacing struct equality, pgx timestamp representation fix.", - "Tests run in testTx (fixtures_integration_test.go) rolled-back transactions; per-test IDs derived from t.Name() sha1 (L348-L353) avoid cross-test collisions.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/business_system_prompt_repository.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "00777b3c0c14e9a9e8339eefc05df84455bba2c43f2363b3850f8ef703587a34", - "review_fingerprint": "00777b3c0c14e9a9e8339eefc05df84455bba2c43f2363b3850f8ef703587a34", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/business_system_prompt_repository_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "746000ef3d00aab88e90f571f27a3ed46c027bf2b3868a44165b509d8cae1f64", - "review_fingerprint": "746000ef3d00aab88e90f571f27a3ed46c027bf2b3868a44165b509d8cae1f64", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/business_system_prompt_revision_bus.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "e1b42bfc78643c7d2764521f4354cf798bb2c558a80a5f05ff67255c6112a2a1", - "review_fingerprint": "e1b42bfc78643c7d2764521f4354cf798bb2c558a80a5f05ff67255c6112a2a1", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/business_system_prompt_revision_bus_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0c0a6bf9b7910dee6f61f3b13a45bb33e28b0a0ecbae52b71c6e136f440ea384", - "review_fingerprint": "0c0a6bf9b7910dee6f61f3b13a45bb33e28b0a0ecbae52b71c6e136f440ea384", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/channel_monitor_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c782107b396ea3f0cbfa8ea53cd0df506f329481d341637b57b728536b02ff0f", - "review_fingerprint": "c782107b396ea3f0cbfa8ea53cd0df506f329481d341637b57b728536b02ff0f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "渠道监控 v1 仓储:CRUD 走 ent,聚合(DISTINCT ON 最新、可用率、日 rollup UPSERT、watermark、分批清理)走原生 SQL。下游相对上游仅移除 pq.Array,三处 ANY($1) 直接传 []int64/[]string(pgx stdlib 原生数组绑定)。rollup 用 ON CONFLICT (monitor_id,model,bucket_date) DO UPDATE 幂等回填,明细/rollup 清理按 id 分批 5000 行防长事务。上游既有监控机制的宿主持久层;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: pq removal at ListLatestForMonitorIDs L433, ListRecentHistoryForMonitors L499 (unnest bigint[]/text[]), ComputeAvailabilityForMonitors L582.", - "UpsertDailyRollupsFor L613-L664 idempotent upsert; deleteChannelMonitorBatched L702-L719 loops 5000-row id batches; API key stored encrypted, decryption in service layer (comment L777).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_monitor_template_duplicate_metadata_unit_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cebebe652f712713095d3c9d64f13479b677e44a7666d4ac5b2545bcb9812082", - "review_fingerprint": "cebebe652f712713095d3c9d64f13479b677e44a7666d4ac5b2545bcb9812082", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "sqlmock 单元测试(//go:build unit):验证 ApplyToMonitors 在同一事务里先 ent UpdateMany 再合并 extra_headers、保留内部 duplicate operation ID 元数据键,且 header 行数与第一步不一致时回滚。下游相对上游把期望参数从 pq 文本数组字面量 {41,42} 改为 []int64 并注入 pgxSQLMockValueConverter,与仓储的 pgx 数组绑定迁移保持一致,证明迁移后语句参数形态。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: sqlmock.ValueConverterOption(pgxSQLMockValueConverter{}) L20/L64 and []int64{41,42} args L48/L81 replacing pq array literals.", - "Asserts atomic two-statement apply with jsonb || CASE preservation of duplicate-op key and rollback on row-count mismatch (EqualError L92).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_monitor_template_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c50a52bb694c626c1c3f52879576d96e5cc2bbbf2ab515b4f44070f884ef4a88", - "review_fingerprint": "c50a52bb694c626c1c3f52879576d96e5cc2bbbf2ab515b4f44070f884ef4a88", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "监控请求模板仓储:模板 CRUD 与 ApplyToMonitors。Apply 在一个事务内先按 template_id+IDIn+provider+api_mode 四重过滤 ent 批量更新,再用 jsonb || CASE 合并 extra_headers 且保留内部 duplicate operation ID 键,行数不一致即报错回滚(配套单测覆盖)。下游相对上游仅移除 pq.Array,ANY($4) 直接传 []int64。宿主监控机制持久层;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: single change at applyToMonitorsWithClient L194-L195 (monitorIDs passed directly, pq import dropped).", - "Transaction boundary: ApplyToMonitors reuses ctx tx or opens one (L116-L138); header merge row-count check L199-L205 guards partial application.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_monitor_v2_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d2bb4cbb50327781f3f1593edcd0178b50aa6c3f1624b9597bc0a5adb79766bc", - "review_fingerprint": "d2bb4cbb50327781f3f1593edcd0178b50aa6c3f1624b9597bc0a5adb79766bc", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "渠道监控 v2 仓储(原生 SQL):单例配置行(id=1、version CAS,WHERE version=$8 未命中返回 ErrChannelMonitorV2ConfigConflict)、facts/histogram/error 三类 1m 与 rollup 表的聚合读取、观众组权限收敛(RestrictGroups 与配置 group 白名单求交,空交集直接 FALSE 或零查询返回)、忽略错误类别对 error_rate 的调分。下游相对上游仅做 pq→pgx 迁移:数组入参直接传切片,数组列扫描改用 pgtype.NewMap().SQLScanner。宿主观测聚合机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: pgtype.SQLScanner for group_ids/ignored_error_categories scans (L25,L33,L69,L83); direct slice args at L669,L768,L777,L1172,L1181,L1452,L1495,L1548.", - "UpdateConfig optimistic CAS L70-L88; channelMonitorV2ScopedGroupIDs L609-L632 intersects viewer allow-list; loadErrorDetails admin-only raw ops_error_logs scan with LIMIT 400 and secret masking via sanitizeChannelMonitorV2ErrorDetail (L837-L853).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_monitor_v2_repo_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cb48cc0c16d3f661b71b5f2e5ad06808c5771e3ceb1653c736f08c183e980068", - "review_fingerprint": "cb48cc0c16d3f661b71b5f2e5ad06808c5771e3ceb1653c736f08c183e980068", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "监控 v2 仓储单元测试(sqlmock + 纯函数)。断言:date_bin 原点为 UTC 且各 rollup SQL 引用一致、显示模型按平台折叠语义、观众组作用域(RestrictGroups 交集、空作用域零查询直接返回空结果)、错误聚合 SQL 含 90 分钟有界去重与 composite 平台解析、留存策略常量、applyIgnoredErrors 只调整比率不动绝对量。下游相对上游把 pq.Array 期望改为裸 []int64,与仓储 pgx 数组绑定一致。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: require.Equal(pq.Array([]int64{...})) -> []int64 at L125 and L163; pq import dropped.", - "Key proofs: empty restricted scope returns without queries (mock.ExpectationsWereMet with no expectations, L178-L277); SQL taxonomy needles L386-L404; retention rules per rollup tier L336-L375.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0c11a784d6ae315e0590704bc53fb489b52f578e2895d9be7cf56cf45101a93b", - "review_fingerprint": "0c11a784d6ae315e0590704bc53fb489b52f578e2895d9be7cf56cf45101a93b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "渠道(channel)CRUD 仓储:channels 主表 + channel_groups 关联 + 模型定价/账号统计定价的事务式整体替换,列表批量加载避免 N+1。下游相对上游仅移除三处 pq.Array(batchLoadGroupIDs、GetGroupsInOtherChannels、GetGroupPlatforms 直接传 []int64)。runInTx 统一事务边界,唯一冲突经 isUniqueViolation 转 ErrChannelExists。宿主渠道机制持久层;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: pq removal at L372, L455, L530 only.", - "Create/Update wrap group + pricing replacement in one tx (L37-L82, L121-L170); List batch-loads groups/pricing/stats rules (L248-L266).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_repo_account_stats_pricing.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5d0fde0f9b0381275f3d21d93235d670594e6031f1f4af8041a9b9b14dff1d9b", - "review_fingerprint": "5d0fde0f9b0381275f3d21d93235d670594e6031f1f4af8041a9b9b14dff1d9b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "渠道『账号统计定价规则』持久层:规则(group_ids/account_ids 数组列)+ 模型定价 + 阶梯区间的三层批量加载与事务内整体替换(DELETE 后逐条 INSERT,靠外层 tx 原子性,子表靠 CASCADE)。下游相对上游仅 pq→pgx:入参直接传切片,数组列扫描用 pgtype.NewMap().SQLScanner。计费/定价持久机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: pgtype scanner L30-L35, direct slice args L21,L73,L156,L225.", - "replaceAccountStatsPricingRulesTx L134-L149 delete+reinsert inside caller tx; interval persistence mirrors channel_pricing_intervals (L191-L212).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_repo_pricing.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "49b5720d4e3e22aadab2a70aa838be1403d5111daca7b624290e9f28b5e87a31", - "review_fingerprint": "49b5720d4e3e22aadab2a70aa838be1403d5111daca7b624290e9f28b5e87a31", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "渠道模型定价持久层:channel_model_pricing + channel_pricing_intervals 的 CRUD、批量加载与事务式替换,time_pricing JSONB 序列化(空配置写 SQL NULL)。下游相对上游仅 pq→pgx:isUniqueViolation 改判 pgconn.PgError 23505,setGroupIDsTx/批量查询直接传切片给 unnest/ANY。定价属计费机制持久层;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: pgconn.PgError unique-violation check L318-L325; direct slice args L101,L144,L224.", - "marshalChannelTimePricing returns nil (SQL NULL) for empty periods L271-L280; malformed time_pricing JSON is a hard error (L191-L194), models JSON falls back to empty slice (L188-L190).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_repo_pricing_time_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "19931dc24d4a18d63e553878167cd127d7b0fa5f9aaad180c2ce719594b4d5a0", - "review_fingerprint": "19931dc24d4a18d63e553878167cd127d7b0fa5f9aaad180c2ce719594b4d5a0", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "sqlmock 单元测试(//go:build unit):验证 time_pricing 列的读写回环——列表读出 JSON 解析为 ChannelTimePricing、SQL NULL 映射 nil、坏 JSON 报 unmarshal 错、Create/Update 在禁用(nil 或空 periods)时写 SQL NULL。下游相对上游仅在 sqlmock.New 注入 pgxSQLMockValueConverter,适配 pgx 参数形态。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: single change L27 adds pgxSQLMockValueConverter to sqlmock.", - "Asserts NULL/malformed handling L64-L90 and NULL write-back when disabled L133-L181.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/channel_repo_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "18eece5fcab95c4198775a7ac101cda41f45a6b3f2a218cbca9739fadcd854ba", - "review_fingerprint": "18eece5fcab95c4198775a7ac101cda41f45a6b3f2a218cbca9739fadcd854ba", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "channel 仓储纯函数单元测试:marshal/unmarshalModelMapping 回环与容错(坏 JSON 归 nil)、escapeLike 转义 LIKE 特殊字符、isUniqueViolation 判定(含 wrapped 与 typed-nil 场景)、channelListOrderBy 允许 id DESC。下游相对上游把 pq.Error 测试用例整体换成 pgconn.PgError,证明 pgx 迁移后 23505 判定含 typed-nil 防护仍成立。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: TestIsUniqueViolation cases switch pq.Error -> pgconn.PgError (L182-L228), including typed-nil guard L204-L210.", - "Other assertions (model mapping round-trip, escapeLike, order-by) unchanged from upstream.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/cindy_account_stats_reset_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bcb8556ee17c2813690140ce79f6656720b8125cc106aa22d17bb176f771be56", - "review_fingerprint": "bcb8556ee17c2813690140ce79f6656720b8125cc106aa22d17bb176f771be56", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "//go:build unit 的源码形状守卫测试:读取同目录 usage_log_repo_stats.go 原文转小写,断言 'greatest($2, coalesce(a.cindy_account_stats_reset_at' 至少出现 3 次且含 'group by ul.account_id',即账号 today/window 单查与批量三条统计 SQL 都把窗口下界钳到 Cindy 专用统计水位(migrations/238 新增的 accounts.cindy_account_stats_reset_at,NULL 时经 COALESCE '-infinity' 对其他平台零影响)。它只证明 SQL 文本形状,不证明查询结果;实际出现次数为 L287/L318/L356 正好 3 处,GROUP BY 在 L357。rg 确认 backend 与 plugins 内均无该列的写入者(仅迁移定义列),与既有 usage_log_repo_stats.go 记录一致:水位由运维/域侧设置,核心只读,无第二执行器。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S53-cindy-rest-T3-review.json", - "L14-L18 以 os.ReadFile 读源文件并做 strings.Count>=3 与 Contains 断言;若统计 SQL 被重写去掉水位钳制,此测试会在 unit 标签下失败。", - "守卫对象:usage_log_repo_stats.go GetAccountTodayStats L287、GetAccountWindowStats L318、GetAccountWindowStatsBatch L356-L357(LEFT JOIN accounts + GREATEST/COALESCE)。", - "rg -i 'stats_reset|StatsResetAt' 在 backend/internal、plugins、frontend/src 中无写入路径命中,仅 migrations/238(列+partial index)与两处守卫测试;watermark 无代码写者属已知设计事实,不作为缺陷上报。", - "相对上游 aea725f 为全新文件;未执行测试,不宣称通过。" - ] - }, - { - "path": "backend/internal/repository/cindy_account_view_atomic_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4d36dfe9b61fd77e5da8ae92bb7037e3362c08cac7a2784d4201a3cd9dd3124f", - "review_fingerprint": "4d36dfe9b61fd77e5da8ae92bb7037e3362c08cac7a2784d4201a3cd9dd3124f", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/cindy_balance_probe_complete_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f84e4b4ec49158b9eb0d05aa75f07aa0b07d36e4c845e706718a3f6e06e8fcd1", - "review_fingerprint": "f84e4b4ec49158b9eb0d05aa75f07aa0b07d36e4c845e706718a3f6e06e8fcd1", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "PostgreSQL 集成测试,针对 cindy_balance_probe_repo.go CompleteStage(L678)的账号快照重校验:九个用例证明在同一 Luna 阶段结果下,若账号 credentials 漂移、被禁用、余额标记被清除或被替换、账号被软删除(含 networkFailure=true),item 必须落为 state=skipped_stale / luna_outcome=stale / final_outcome=skipped_stale 且 consecutive_upstream_failures 保持 0(已删除账号的网络失败不得暂停任务);快照未变时按 outcome 落 healthy / luna_exact(无 final_outcome)/ still_exhausted / inconclusive。第二个用例证明 LatestByAccountIDs(L387)暴露的是可翻译的结论状态 healthy 而非阶段结果 success。被测主体是宿主为 Cindy 探测能力提供的持久化状态机,结论规则在插件 catalog/probe.go;此处只固定持久化世代校验,归 cindy-provider 宿主适配。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S53-cindy-rest-T3-review.json", - "L37-L144 表驱动用例,mutate 闭包直接以 SQL 改 accounts.credentials/status/cindy_balance_insufficient_at/deleted_at 并推进 updated_at,制造与 reservation.AccountUpdatedAt/IdentityFingerprint/WasMarked 不一致的世代。", - "L153-L186 调用 CompleteStage 后回读 cindy_balance_probe_items.state/luna_outcome/final_outcome 与 cindy_balance_probe_jobs.consecutive_upstream_failures;所有用例 wantFailures=0,applied 与 keepRunning 均为 true。", - "L216-L292 fixture 以原生 SQL 插入 running 任务与 luna_running item,指纹来自 service.CindyAccountIdentityFingerprint;Cleanup 删除 scheduler_outbox/jobs/account_groups/accounts。", - "调用链:CompleteStage L678、LatestByAccountIDs L387 位于本切片文件 9。相对上游 aea725f 为全新文件;未执行任何数据库或测试。" - ] - }, - { - "path": "backend/internal/repository/cindy_balance_probe_dispatch_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0d4b624d552dc1326b0d1e895ed27fadecc9d8809627e10304972c5521ebd1d7", - "review_fingerprint": "0d4b624d552dc1326b0d1e895ed27fadecc9d8809627e10304972c5521ebd1d7", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "PostgreSQL 集成测试,固定 Terra 阶段派发的权威世代:Luna 阶段 CompleteStage(exact→luna_exact) 后 ReserveNext(仓储 L494)必须返还 Stage=terra、RequestCount=2、LunaAt 非空且 delay=0 的预约;测试内嵌一条比仓储更严的 EXISTS 谓词(含 j.request_count、i.luna_at、credentials JSONB 与 laxarouter base_url 白名单)证明未修改的预约能通过,而 JobRequestCount+1、LunaAt 提前 1 秒、LunaAt 置空三种漂移只被严谓词判为过期,ValidateReservationForSend(L595)仍返回 ready=true——即任务级请求计数与 Luna 时间戳只是观测回显,不能撤销当前 item 派发世代;最后用 SQL 替换 lease_token 证明被回收的任务必须拒绝旧 worker 租约。被测主体是宿主为 Cindy 探测提供的租约/世代持久化,探测结论规则在插件 catalog/probe.go,归 cindy-provider 宿主适配。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S53-cindy-rest-T3-review.json", - "L34-L37 注释说明 worker 校验的是仓储回读的账号而非 Ent 创建输入(PostgreSQL 微秒截断),与仓储 L610 的 Truncate(time.Microsecond) 比较一致。", - "L105-L139 严谓词 SQL 与 L140-L145 ready 断言;L147-L181 三个 driftCases 断言 strictPredicateMatches=false 但 ValidateReservationForSend=true;L183-L192 替换租约后 ready=false。", - "调用链:CompleteStage L678 → ReserveNext L494 → ValidateReservationForSend L595-L640+(UPDATE ... FROM jobs JOIN accounts 的 CAS 快照,注释 L631-L634 明确 request_count/luna_at 只作诊断回显)。", - "相对上游 aea725f 为全新文件;未执行任何数据库或测试,不宣称通过。" - ] - }, - { - "path": "backend/internal/repository/cindy_balance_probe_finalize_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "27a3636aa52e30186cb8600326bc3ffbb39f8095a2a83a4a191845073fda6fe8", - "review_fingerprint": "27a3636aa52e30186cb8600326bc3ffbb39f8095a2a83a4a191845073fda6fe8", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/cindy_balance_probe_lifecycle_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e677a5898a395aa21001ebbddb98239d6cc24d3e7761e0f86b472fd9bef0aee4", - "review_fingerprint": "e677a5898a395aa21001ebbddb98239d6cc24d3e7761e0f86b472fd9bef0aee4", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/cindy_balance_probe_repo.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "37373969e906749783d034ba625133ee5064bb485aa809bee4d55b93fd4d7c6e", - "review_fingerprint": "37373969e906749783d034ba625133ee5064bb485aa809bee4d55b93fd4d7c6e", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/cindy_balance_probe_repo_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "591dbe5ff6047b6dfb062a9fd10fc7d0458b0aab65ac20229b171c826d723b5a", - "review_fingerprint": "591dbe5ff6047b6dfb062a9fd10fc7d0458b0aab65ac20229b171c826d723b5a", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/cindy_group_identity.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "d0afa3da68ec9390a2366902f9eb005e69f28f04c16315328b2806df056a7bac", - "review_fingerprint": "d0afa3da68ec9390a2366902f9eb005e69f28f04c16315328b2806df056a7bac", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/cindy_health_repo.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "a7f715234eee092744e98e2d601cf7ae80f0fc115850eabb1d3336ed461417f3", - "review_fingerprint": "a7f715234eee092744e98e2d601cf7ae80f0fc115850eabb1d3336ed461417f3", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/cindy_health_repo_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1778dbbf50f0de4b134a5d1068364ebdd395fd99015cc437b4550a4f1e7306ec", - "review_fingerprint": "1778dbbf50f0de4b134a5d1068364ebdd395fd99015cc437b4550a4f1e7306ec", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/codex_fingerprint_seed_migration_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d22abe40d589d1983bfadc0874e3c59cbe36b39a43faf3f22f19a7f4940f727f", - "review_fingerprint": "d22abe40d589d1983bfadc0874e3c59cbe36b39a43faf3f22f19a7f4940f727f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "集成测试(//go:build integration):验证迁移 225 只给 openai+oauth 且 codex_fingerprint_mode 非 off 的账号回填 codex_fingerprint_seed(缺失/空/坏值补 UUID,合法值与 off/apikey 不动),且重跑幂等;BulkUpdate 的 EnsureCodexFingerprintSeed 每行独立 gen_random_uuid、重试不轮换已有合法种子、apikey 账号不写种子。种子语义服务于 codex-runtime 域,但被测对象是迁移 SQL 与 account 仓储的数据层保证。下游相对上游仅清理语句移除 pq.Array。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: cleanup DELETE ... ANY($1) passes []int64 directly (L115-L116); pq import dropped.", - "Proofs: canonical UUID + idempotent rerun L61-L86; per-row distinct seeds and no-rotate retry L136-L148; guarded by integration build tag + fixtures testTx/integrationDB DSN gate.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/concurrency_cache_live_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "48f4a956dd65fa8a2c788e8d5b051171938b3dbc42390717d1e878217cdcba0b", - "review_fingerprint": "48f4a956dd65fa8a2c788e8d5b051171938b3dbc42390717d1e878217cdcba0b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "miniredis 单元测试(无 build tag)。上游既有部分证明 Live 租约置换普通并发槽并计入上限、无续租 61s 过期后普通槽可复得。下游新增 TestAccountTrafficObserveBeginReadsSlotsAndRollingMinute:证明新的 AccountTrafficObserveCache 采样(Begin 计数、PeakInFlight 读并发 ZSET、基于 Redis TIME 的 60s 滚动窗口、观察者 turn Finish 记 Upstream429)且采样不改动并发 ZSET。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Downstream delta = new test L74-L115: rolling-minute drop after SetTime(+61s), Started/PeakInFlight/RequestsLast60s assertions, sampling leaves GetAccountConcurrency at 2, observer turn counts one 429 per turn (two Finish calls, Upstream429==1).", - "Runs entirely against miniredis; no real Redis or DB.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/dashboard_aggregation_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "10d4cb5060abfcf58a434e8d6a4b2841764db9e07edb7aa6696c8fc253cf6620", - "review_fingerprint": "10d4cb5060abfcf58a434e8d6a4b2841764db9e07edb7aa6696c8fc253cf6620", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "仪表盘预聚合仓储:usage_logs 小时/日聚合 UPSERT(ON CONFLICT 幂等)、活跃用户去重表、watermark、按 ctid 分批清理(每批 10000)并联动 group_usage_rollup 失效标记(同事务 + lockGroupUsageRollupState),分区表按月建删。下游相对上游为 pq→pgx:驱动探测改 stdlib.Driver,标识符引用改 pgx.Identifier.Sanitize,新增 quotePostgresLiteral(仅用于内部格式化的日期字面量,无注入面)。宿主用量聚合机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: isPostgresDriver L49-L55 (stdlib.Driver), partition DDL quoting L640/L663/L673-L678, quotePostgresLiteral L683-L685.", - "Rollup invalidation is transactional with the destructive step (cleanupUsageLogsBatchWithRollupInvalidation L287-L345, dropUsageLogsPartitionWithRollupInvalidation L647-L667).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/db_pool.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "87cf047a3d6d13d054e4755046a79513edadef88082bcb9a0fc2bdcaed967197", - "review_fingerprint": "87cf047a3d6d13d054e4755046a79513edadef88082bcb9a0fc2bdcaed967197", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "数据库连接池参数钳制:conn_max_lifetime/idle_time 非法或超 24h 时回退安全默认(30m/5m)并告警。下游相对上游仅改包注释——原注释把钳制描述为 lib/pq watchCancel 阻塞的临时缓解并预告迁移 pgx,迁移完成后改述为通用的陈旧连接回收理由。无行为改动;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: package comment only (L1-L5); clamp logic unchanged (L29-L49).", - "applyDBPoolSettings logs effective values L51-L66.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/db_pool_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a957df00951c0b07d97309d4d2e8a3dfea7f67ef8f5fb8d59a6a175a37afee9c", - "review_fingerprint": "a957df00951c0b07d97309d4d2e8a3dfea7f67ef8f5fb8d59a6a175a37afee9c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "连接池钳制单元测试:零/负值/超 24h 回退默认、合理值透传、applyDBPoolSettings 生效到 db.Stats()。下游相对上游把 sql.Open(\"postgres\")(lib/pq 匿名导入)换成 OpenPostgresDB(pgx stdlib,postgres_driver.go),证明迁移后设置仍可应用;懒连接、不实际拨号。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: L79 OpenPostgresDB replaces sql.Open + pq blank import removal.", - "Assertions cover fallback matrix L11-L67 and MaxOpenConnections passthrough L85-L88.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/ent.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f7f5a5efcc39575f210dfd5f691c2a0badddf2814ce23f98a53771454853ea7c", - "review_fingerprint": "f7f5a5efcc39575f210dfd5f691c2a0badddf2814ce23f98a53771454853ea7c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Ent/数据库初始化:时区、DSN、pgx 建连(openPostgresDB,含 server-timing 连接器开关)、迁移重试(仅瞬态错误,指数退避 8 次封顶 30s)、bootstrap 密钥、SIMPLE 模式默认分组种子。下游相对上游把双分支 pq/entsql.Open 建连合并为 openPostgresDB,并在 f8d4ed52b 让 isTransientDatabaseInitializationError 同时识别 *pgconn.PgError 与遗留 *pq.Error(errors.As 穿透包装、typed-nil 防护,SQLSTATE 57P03 或 08 类才判为瞬态)。复审于 f8d4ed52b:重试预算(最多 8 次重试/9 次尝试)、1s 起倍增封顶 30s 的退避、非瞬态错误与 ctx 取消立即返回均未改动;配套 ent_init_retry_test.go 已改为伪造 pgconn.PgError 并断言完整退避阶梯。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: InitEnt unified pgx open path via openPostgresDB (unchanged by f8d4ed52b, which per git show touched only the pgconn import L21 and the transient predicate); pq import retained for legacy callers.", - "Fix f8d4ed52b re-reviewed: isTransientDatabaseInitializationError L79-L94 switches on errors.As(*pgconn.PgError) then errors.As(*pq.Error), both nil-guarded, then SQLSTATE 57P03 or prefix 08 -> transient; retry loop L43-L66 unchanged (maxDatabaseInitializationRetries=8 at L26, base 1s doubling capped 30s, non-transient error or wait/ctx error returns immediately).", - "Companion ent_init_retry_test.go (outside this slice) now fabricates pgconn.PgError (L16-L18); table covers pgx 57P03 and wrapped 08006 true, 28P01/23514/57P01, message-only SQLSTATE, net.OpError, nil, typed-nil pgx/pq, context errors false, legacy pq true (L26-L40); fail-fast table asserts 1 attempt and no wait (L69-L96); limit test asserts 8 retries/9 attempts with ladder 1,2,4,8,16,30,30,30s (L114-L133).", - "git diff f8d4ed52b..HEAD(52424fb7a) is empty for both files and the working tree is clean for both; sha256 self-computed at re-review.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/ent_init_retry_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "329af589f17fd1c8c190e78677c1876009d92257170cfb0f15e00f9c0f0b83e8", - "review_fingerprint": "329af589f17fd1c8c190e78677c1876009d92257170cfb0f15e00f9c0f0b83e8", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "全文复核六个直接分类/retry方法:生产pgconn及legacy pq包装/typed nil、57P03/08策略、永久auth/constraint/数据错误与ctx不重试、8次虚拟退避共9次尝试。最后map模拟仅证明回调重试保留其自身状态,不作为数据库迁移原子性证明;没有真实sleep/DB。", - "evidence": [ - "artifacts/evidence/v027-astra-pgx-startup-retry-review.json", - "Parent read the entire fixture and matched current SHA; only the report-specific targeted commands were run." - ] - }, - { - "path": "backend/internal/repository/error_translate.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a229085168fcb99528c08697e4f4e8ed79276598ec5e3d357fbbfcec9d4eaec5", - "review_fingerprint": "a229085168fcb99528c08697e4f4e8ed79276598ec5e3d357fbbfcec9d4eaec5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "仓储层错误翻译:clientFromContext 事务感知取 client;translatePersistenceError 把 sql.ErrNoRows/ent NotFound 映射业务 notFound、唯一约束冲突映射 conflict。下游相对上游把唯一约束检测从 *pq.Error 改为 *pgconn.PgError(补 typed-nil 防护),保留错误消息关键词回退。宿主数据机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: isUniqueConstraintViolation L86-L89 pgconn.PgError with nil guard; message-keyword fallback L93-L96 unchanged.", - "Used by ent-based repos via translatePersistenceError L50-L69.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/fixtures_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "db395a062de2805ce4b13e84e072f3f09633bda08052d7cfa50730dbe7075357", - "review_fingerprint": "db395a062de2805ce4b13e84e072f3f09633bda08052d7cfa50730dbe7075357", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "集成测试夹具(//go:build integration):mustCreateUser/Group/Proxy/Account/ApiKey/RedeemCode/Subscription/BindAccountToGroup 一组建数据 helper,带默认值填充。下游相对上游给 Group/Account 夹具补 wire_platform/provider_profile 两列并给 Account 透传 CindyBalanceInsufficientAt,支撑下游 provider 身份拆分(cindy)相关集成测试。DSN 门禁在 integration_harness_test.go(TestMain:显式 SUB2API_TEST_POSTGRES_ONLY_DSN 或 testcontainers 临时库,pgx/v5 驱动),不会隐式连生产库。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: SetWirePlatform/SetProviderProfile at L89-L90 (group) and L207-L208 (account); CindyBalanceInsufficientAt passthrough L254-L256.", - "Fixture-only file: no assertions of its own; consumed by the repository integration suites.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/gateway_cache.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d65f1befbe078ab08ac779b6c432d043780f570108357d12f22266a21235497b", - "review_fingerprint": "d65f1befbe078ab08ac779b6c432d043780f570108357d12f22266a21235497b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Redis 网关缓存。上游既有:粘性会话、OpenAI Responses 会话窗口 CAS、grok 视频计费 pending/claim、cyber 会话封禁、Live 通话记录与 controller 状态机、reasoning 全文缓存。下游新增三块:(1) DeleteSessionAccountIDIfMatches——Lua CAS 删除,防止旧请求误删并发重绑;(2) OpenAI runtime breaker——按 account+model 的 block/marker/claim/index 键族与 Lua 脚本,半开探测 owner 租约(单/多 scope 原子申领、续租、释放、清除,TTL 只增不减);(3) cindy 余额 pending 与健康 episode 存储——generation 单调比较的 Lua claim、终态 pending(banned/balance_insufficient)、含 v1/v2 旧键清理。cindy 部分把该域的状态词汇编码进核心缓存,见 findings(low)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: adds L79-L98 (CAS sticky delete), L636-L1019 (runtime breaker scripts/keys), L253-L634 (cindy balance/health stores + interface assertions L256-L261).", - "Breaker block script never shortens an existing TTL and extends marker to effective+5m retention (L665-L707); multi-scope claim is one atomic Lua script (L751-L871).", - "Cindy health claim orders generations via length-then-lex compare on numeric strings (L322-L361), avoiding 53-bit float truncation; MarkCindyBalancePending persists without TTL until DB marker commits (L532-L546).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/gateway_cache_cindy_balance_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7f587a63f6ec7a9efc7572b660518c73303463bb4357fc6b5951480970acf24d", - "review_fingerprint": "7f587a63f6ec7a9efc7572b660518c73303463bb4357fc6b5951480970acf24d", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/gateway_cache_live_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e231f5b9b6a7c1bc23aa48944aac03955ec5f0a844f8491c9522d95214229f13", - "review_fingerprint": "e231f5b9b6a7c1bc23aa48944aac03955ec5f0a844f8491c9522d95214229f13", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "miniredis 单元测试。上游既有 Live 通话身份/controller 状态机断言。下游新增:runtime breaker 全套语义证明——阻断期拒探测、迟到成功不解除激活中的 breaker、半开期 owner 独占探测、多 scope 申领原子性(后续 scope 被拒时不留下前面 scope 的 claim)、续租仅限当前 owner 且不复活过期租约、释放保留 marker、Block 不缩短既有 TTL;以及 DeleteSessionAccountIDIfMatches 的 CAS 语义与 WS 会话窗口 claim 返回前任 owner。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Downstream delta (+281) = tests L64-L343: half-open owner exclusivity L86-L104, batch-claim atomicity L107-L135, renew owner safety L137-L214, index TTL restoration L216-L242, release keeps marker L244-L286, TTL monotonicity L288-L302, sticky CAS delete L304-L323, WS window claim L325-L343.", - "All against miniredis with FastForward/SetTime; no external services.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/gateway_cache_reasoning_state.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "59c76cab8bc573f7fc0d06565d0ced9d9046db2ed159820b15667e2f475443a3", - "review_fingerprint": "59c76cab8bc573f7fc0d06565d0ced9d9046db2ed159820b15667e2f475443a3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增:OpenAI reasoning 状态缓存(单 Lua 脚本实现 get/put/delete)。正向 batch 缓存与负向 rejected 缓存分前缀(带 cluster hash tag),条目按 payload sha256 版本化做 CAS 删除,owner 哈希强制租户隔离;全局/租户字节数、条目数、单条字节数四重上限,超限按 LRU 原子逐出,硬 TTL 不被 LRU 触碰延长,过期惰性回收每次至多 128 条。encodeReasoningBatch 校验条目类型白名单(reasoning/message/function_call、仅 completed)。runReasoningState 每次操作克隆共享 client 为单连接、单次拨号、受 OpenAIReasoningStateIOBudget 限时的短命 client(有意设计:不改全局 Redis 选项,测试覆盖)。属网关协议缓存机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "New downstream file (git ls-tree upstream empty): Lua state machine L29-L133 with remove() maintaining lru/expiry/sizes/owners/totals indexes atomically.", - "Isolation & validation: owner==tenant check in get (L70), digest-only keys enforced by validateReasoningStateKeys L166-L177, batch admission rules L184-L216.", - "Per-op bounded client L334-L368: ContextTimeoutEnabled clone, MaxRetries=-1, single dial, closed immediately — deliberate I/O budget design, one fresh connection per operation.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/gateway_cache_reasoning_state_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "269417fc27ff5d3bce333db96c69180e32059f8959bfa0ad27760cabf6c79ac8", - "review_fingerprint": "269417fc27ff5d3bce333db96c69180e32059f8959bfa0ad27760cabf6c79ac8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增 miniredis 单元测试:CAS 回环与 scope/tenant 双重隔离(他租户读不到、CAS 删不掉)、硬 TTL 不因 LRU 触摸延长、正/负缓存命名空间分离且只有新拒绝写入才续负向证据、租户与全局字节/条目上限的原子 LRU 逐出(超大记录被拒且不误删既有条目)、负缓存只存时间戳摘要不存明文、并发写后容量不变式、传输预算(单次拨号、共享 client 选项不被污染、取消的 ctx 不再拨号)。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "New downstream file; proofs anchored at: isolation/CAS L45-L94, hard TTL & negative separation L96-L140, bounded atomic LRU L142-L192, admission validation table L194-L230, digest-only negative store L232-L255, concurrent capacity L257-L279, transport budget & no-retry L281-L352.", - "Transport tests use synthetic dialers (net.Pipe / failing dialer); no network.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/group_model_allowlist_repair_migration_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f0fafeaf6a72a3afec90ab38a030d937cdb2eabe8ecccd65a65b40ab9449497a", - "review_fingerprint": "f0fafeaf6a72a3afec90ab38a030d937cdb2eabe8ecccd65a65b40ab9449497a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "集成测试(//go:build integration):验证可重放修复迁移 236 把历史遗留的 models_list_config 列改回 model_allowlist、双列并存时回填、列缺失时重建为 NOT NULL DEFAULT '{}',且重复执行幂等。下游相对上游新增 TestMigration236PreservesCurrentAllowlist(当前配置在重跑下逐字保留,含混合大小写/通配/opaque 字段),并在删列前先 DROP 迁移 240 的失效触发器以复刻 236 之前的历史 schema——注释明确不弱化生产触发器。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Downstream delta: new preserve test L112-L133 and DROP TRIGGER-before-DROP-COLUMN guard L88-L90 with explanatory comment.", - "requireModelAllowlistColumnShape asserts NOT NULL + '{}'::jsonb default L142-L153; migration read from migrations.FS and applied inside testTx rollback.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/group_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2ec210c9f7975454913d715a8fec85b5b1e2a5c5d3a5b6cd88bffdce4477ceed", - "review_fingerprint": "2ec210c9f7975454913d715a8fec85b5b1e2a5c5d3a5b6cd88bffdce4477ceed", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "分组仓储:ent CRUD + 原生 SQL(存在性、账号计数、级联删除、绑定、排序)+ scheduler outbox 事件。下游相对上游:Create/Update 持久化 wire_platform/provider_profile 两列;groupAccountAvailableSQL 新增 cindy 账号门(platform<>'cindy' 或 余额不足/封禁时间戳均为空才算可用),使分组可用账号计数与调度口径一致;并把多处 ANY($1) 从 pq.Array 改为直接传切片。注意 lockLiveGroups(L47) 仍用 pq.Array,见 findings(low)。宿主分组机制持久层;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: wire_platform/provider_profile on create L101-L102 & update L291-L292; cindy availability gate L988; pq removal at L811,L1022,L1058,L1105,L1153,L1170.", - "Cascade delete locks group FOR UPDATE, soft-deletes subscriptions/routes, hard-deletes joins, in one ent tx (L863-L975); UpdateSortOrders pre-checks all IDs exist then CASE update (L1148-L1191).", - "lockLiveGroups L43-L47 still passes pq.Array(groupIDs) — inconsistent with the pgx migration though functionally equivalent (pq.Array renders the same array text pgx stdlib accepts).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/group_repo_cindy_health_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8508b09d78bbc446da52c4a0b1b9ce674e06c054650c1b920841d0e986db5d11", - "review_fingerprint": "8508b09d78bbc446da52c4a0b1b9ce674e06c054650c1b920841d0e986db5d11", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/group_repo_cindy_split.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "85b3fd9210f0b7f10ec023746df23bd12ff2e6210b57e13c24d01437fec47255", - "review_fingerprint": "85b3fd9210f0b7f10ec023746df23bd12ff2e6210b57e13c24d01437fec47255", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/group_repo_cindy_split_identity_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "14617686b314ccb6db3ed6c940bad72a330563a17b8a07488212985796df687f", - "review_fingerprint": "14617686b314ccb6db3ed6c940bad72a330563a17b8a07488212985796df687f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "cindy-provider", - "reason": "本地 PostgreSQL 合成用例覆盖 canonical 原组、停用成员结构身份、旧投影归普通侧和优先级保持,清理限定本次生成 ID。", - "evidence": [ - "backend/internal/repository/group_repo_cindy_split.go", - ".downstream/implementation-v0.2.7.md#可复用验证" - ] - }, - { - "path": "backend/internal/repository/group_repo_cindy_split_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a5f6e5258dbd05632ff9e94b61b80373d09b0447e3bdfe8f6d9e62e9f6195cfc", - "review_fingerprint": "a5f6e5258dbd05632ff9e94b61b80373d09b0447e3bdfe8f6d9e62e9f6195cfc", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "带 //go:build integration 标签的仓储层集成测试,覆盖 groupRepository.AuditCindyGroups / PreviewCindyGroupSplit / CommitCindyGroupSplit(下游新增,上游 aea725f 无此文件)。断言:审计排除软删除分组并把 1 个 Cindy + 1 个普通账号的分组归为 mixed;预览的 64 位十六进制成员指纹对 last_used_at/status/updated_at 等运行时写入保持不变、对 account_groups.priority 变化则在提交时返回 ErrCindyGroupSplitDrift;成功提交后目标分组继承倍率/利润控制/状态、被标为 platform=cindy + wire openai + laxa_v1、成员按原 priority 迁移、仅选中的 API Key 改绑、账号凭据不变;第二个用例用 scheduler_outbox 上的 BEFORE INSERT 触发器强制失败,证明目标分组、成员、Key 绑定和 outbox 事件全部回滚。被测对象是核心仓储层为 Cindy 分组拆分提供的事务执行器,其分类/迁移方向决策来自 service.CindyGroupPartitionPlan(插件 cindy-provider 的 partitionGroup),因此归 cindy-provider;仅静态阅读,未执行(需要 integration 数据库)。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S54-cindy-rest-T4-review.json", - "L15-L188 TestCindyGroupSplitPreviewDriftAndAtomicCommit: audit excludes deleted_at groups (L91-L94), mixed classification counts (L96-L99), preview counts + 64-char MemberFingerprint (L106-L112), fingerprint invariant under runtime writes (L118-L146), priority change -> ErrCindyGroupSplitDrift (L148-L158), commit copies RateMultiplier/Profit* and sets PlatformCindy/WirePlatformOpenAI/ProviderProfileCindyLaxaV1 (L165-L181), membership priority 18/29 and key rebinding (L183-L186), credentials untouched (L188-L195).", - "L197-L342 TestCindyGroupSplitRollsBackAllWritesWhenOutboxInsertFails: plpgsql trigger on scheduler_outbox raises for the target group; asserts zero target groups, 2 source memberships, zero moved memberships, key still on source, zero outbox rows.", - "Call chain: subject methods defined in backend/internal/repository/group_repo_cindy_split.go L39/L120/L133; the repo consumes snapshot.plan (service.CindyGroupPartitionPlan: TargetCindy L163, MoveCindy L177, SourceCindy L213) rather than re-deriving classification; plugin-side decision is plugins/cindy-provider/catalog/management.go partitionGroup (L85-L113). Types/errors in backend/internal/service/admin_cindy_group_split.go L13-L65.", - "git ls-tree aea725f -- prints nothing: whole file is downstream delta. Test read statically only; not executed, no database used." - ] - }, - { - "path": "backend/internal/repository/group_repo_cindy_split_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "727098354b098b794402bc84c8b3643b68c163f5f6d79b820ccc0f82d2b00031", - "review_fingerprint": "727098354b098b794402bc84c8b3643b68c163f5f6d79b820ccc0f82d2b00031", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/group_usage_rollup_trigger_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "dcc36c7c876e084f57a1c4e2d2647aed76ba7bafa4f9ad809fd4f17622e11649", - "review_fingerprint": "dcc36c7c876e084f57a1c4e2d2647aed76ba7bafa4f9ad809fd4f17622e11649", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "集成测试(//go:build integration):在临时 schema 内加载迁移 222/223,验证分组用量日 rollup 触发器——级联删除历史行使水位失效、迟到历史写入与水位发布串行化(靠 FOR UPDATE 锁 + pg_stat_activity 等锁探测)、跨零点写入与发布串行、当天写入不推进水位、按会话时区跨 DST 计算 bucket,以及 SyncGroupUsageRollups 换时区后重建。下游相对上游为 pq→pgx:标识符引用改 pgx.Identifier.Sanitize,会话时区改 set_config('TimeZone',...,true),且把易受测试机时区影响的 AT TIME ZONE 'Asia/Shanghai' 断言改用会话内 CURRENT_DATE 抓取的 insertDate 比较(消除测试竞态)。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: pgx.Identifier.Sanitize replaces pq.QuoteIdentifier (L120,L196,L409,L470); set_config TimeZone replaces SET LOCAL TIME ZONE + pq.QuoteLiteral (L480); midnight test compares against session-captured insertDate (L157-L158,L199).", - "Serialization proof uses pg_stat_activity wait_event_type='Lock' polling (L484-L516); schema torn down via DROP SCHEMA CASCADE cleanup.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/http_upstream.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "984848f0248c13648deb08dadbc542e52059c8421e7fec9aed40140f3ce231b2", - "review_fingerprint": "984848f0248c13648deb08dadbc542e52059c8421e7fec9aed40140f3ce231b2", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "通用 HTTP 上游服务:按隔离策略缓存 http.Client + 连接池、协议模式(default/long_stream_h2/openai_h1/h2/h1_fallback/grok)、TLS 指纹传输、Grok CLI 身份注入与 403 回退、响应解压。下游相对上游新增 openai_h1_noreuse(harvest:DisableKeepAlives + 每次新建 CONNECT 便于换出口 IP),并对 OpenAI 传输关闭 Go 自动 gzip 协商(DisableCompression,匹配真实 Codex 客户端不发 Accept-Encoding 的指纹)。缺陷:DisableCompression 的门 isOpenAIUpstreamProtocolMode 未包含 harvest 的 h1_noreuse,见 findings。请求转发/协议属核心网关机制;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: upstreamProtocolModeOpenAIH1NoReuse const L103 + resolveProtocolMode harvest branch L1018-L1020 + transport case L1359-L1365; DisableCompression gate L1342-L1347 + isOpenAIUpstreamProtocolMode L1377-L1384; TLS-fingerprint transport now sets DialContext/TLSHandshakeTimeout L1420-L1421.", - "decompressResponseBody handles gzip/br/deflate/zstd and strips Content-Encoding/Length (L1503-L1550); harvest gap: h1_noreuse omitted from isOpenAIUpstreamProtocolMode so harvest still emits Accept-Encoding: gzip unlike sibling OpenAI modes.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/http_upstream_compression_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "62c5e3663a5faee2e9f485736e9c921f9a9e424651a720e278826fb99a44cc31", - "review_fingerprint": "62c5e3663a5faee2e9f485736e9c921f9a9e424651a720e278826fb99a44cc31", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增单元测试(无 build tag):断言 buildUpstreamTransport 对 openai_h2/openai_h1/openai_h1_fallback 三种模式设 DisableCompression=true,对 default 模式为 false,锁定「OpenAI 传输不自动附加 Accept-Encoding: gzip」的指纹行为。未覆盖 harvest 的 openai_h1_noreuse 模式(与 http_upstream.go 的 finding 相印证)。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "New downstream file: table over three OpenAI modes L11-L15 + default false L16-L18.", - "Coverage gap: harvest noreuse mode not asserted here, matching the http_upstream.go low finding.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/http_upstream_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3db75cf7ed836daeda9004884f4be94f5326041495238bc01b136c78ced8fae9", - "review_fingerprint": "3db75cf7ed836daeda9004884f4be94f5326041495238bc01b136c78ced8fae9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "上游服务测试套件(sqlmock 无关,用 httptest/roundTripFunc/自建 SOCKS5)。上游既有:重定向禁用、明文 HTTP 不绕代理、TLS 指纹 HTTPS 代理回退、Grok CLI 身份与 403 回退、协议模式选择、连接池隔离/淘汰、公网校验每跳。下游相对上游只新增 TestOpenAIHarvestProfileDisablesKeepAlives:断言 harvest profile 解析为 openai_h1_noreuse 且 DisableKeepAlives=true、非 H2、MaxIdleConns=0。该测试未断言 DisableCompression(与 http_upstream.go finding 呼应)。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Downstream delta = one new test L695-L705 asserting harvest keep-alive disable + noreuse mode.", - "Test does not check transport.DisableCompression for harvest, leaving the Accept-Encoding gap uncovered.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/image_studio_job_repo.go", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "dd6816bb1f048dd744d5e47f709642a3d67d4fa6df510bcdee4fe7640083ec02", - "review_fingerprint": "dd6816bb1f048dd744d5e47f709642a3d67d4fa6df510bcdee4fe7640083ec02", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "下游新增:Image Studio 作业仓储(image_studio_jobs/items/artifacts 的原生 SQL 状态机)。实现创建(每图一 item + 输入工件、活跃作业唯一冲突→ErrImageStudioActiveJob)、按 user_id 强作用域的读取、取消/重试、worker 领取(CTE + FOR UPDATE OF item SKIP LOCKED 单条领取,单调置 running)、成功/失败完成并 refresh 计数、finalize 终态判定、过期请求清空 prompt、留存清理。这是 image-tools 插件域的业务持久化(作业生命周期与工件保留规则),而非中立宿主机制,故判 plugin/image-tools。Codex 可能正改动 host mechanism 类文件,本文件按 image-tools 归属。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "New downstream file (git ls-tree upstream empty). Ownership: encodes image-generation domain lifecycle (modes, terminal-status resolution via service.ResolveImageStudioTerminalStatus L533, retention windows).", - "Identity scoping: every user-facing read joins image_studio_jobs.user_id (Get L157, ListItems L195, ListOutputArtifacts L222, GetArtifact L242); worker ClaimNext skips canceled/expired jobs and uses SKIP LOCKED (L387-L396).", - "Monotonic/terminal guards: item updates gated on status='running' (CompleteSuccess/Failure), Finalize only transitions when no active items and not already terminal (L524-L544).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/image_studio_job_repo_test.go", - "candidate_owner": "image-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "007319f8f08d1e0642afba095fc3b49aa20a9cdc9d02eff2133a749372e37973", - "review_fingerprint": "007319f8f08d1e0642afba095fc3b49aa20a9cdc9d02eff2133a749372e37973", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "下游新增 sqlmock 单元测试(//go:build unit):断言 Create 为每张请求图各插一条 item(4 图→4 次 INSERT)并写输入工件、Get 按 user_id 作用域(未命中→ErrImageStudioNotFound)、ExpireRequests 用 FILTER 计数保留已成功条目数。属 image-tools 域仓储行为验证。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "New downstream file: per-image item persistence L34-L38, owner-scoped Get L72-L78, expire preserves succeeded counts L88-L90.", - "sqlmock-only; no real DB. Ownership follows image_studio_job_repo.go (image-tools).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/integration_harness_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "14e5f1732bb108e70adafeaca304201608a571810030aa4c0a943366865030ee", - "review_fingerprint": "14e5f1732bb108e70adafeaca304201608a571810030aa4c0a943366865030ee", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Fully inspected the explicit local-only PostgreSQL mode, which restricts host to 127.0.0.1, nondefault port, codex_test role and disposable sub2api_test_* database. It applies actual migrations and calls m.Run; unavailable Redis is skipped explicitly. The targeted execution used this mode, not Docker's skip-success path.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Source inspection is not represented as an executed test." - ] - }, - { - "path": "backend/internal/repository/migrations_historical_preflight.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "37146cfeaf9baf604bb1e0f3ddde5b992448660a896ca77f35be79b52885c9f4", - "review_fingerprint": "37146cfeaf9baf604bb1e0f3ddde5b992448660a896ca77f35be79b52885c9f4", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/migrations_historical_preflight_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "523ade7b133064712871892fbcdb73e8d479bb37eb2d52ef6601cce6911ed98c", - "review_fingerprint": "523ade7b133064712871892fbcdb73e8d479bb37eb2d52ef6601cce6911ed98c", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/migrations_runner.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "86fe7a865fde9e73440c2df2743373c08ae14d7fa0070ea9c39e879506df2ae3", - "review_fingerprint": "86fe7a865fde9e73440c2df2743373c08ae14d7fa0070ea9c39e879506df2ae3", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/minimax_cindy_quota_migration_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fa219340ed4da8dd244027e1849f105bba73edc7c393f73c832dc372f0508c79", - "review_fingerprint": "fa219340ed4da8dd244027e1849f105bba73edc7c393f73c832dc372f0508c79", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/openai_oauth_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "11b6a44da2def44d1c77b458da0821b24c70d19631c743a218331e857384565b", - "review_fingerprint": "11b6a44da2def44d1c77b458da0821b24c70d19631c743a218331e857384565b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI OAuth 客户端:授权码换取与刷新 token,出站带 Codex 规范身份(User-Agent + originator)。下游相对上游新增 RefreshTokenWithIdentity——允许按账号传入显式 Codex 身份(UA+originator),二者均非空才覆盖,否则回退 CodexCanonicalAuthIdentity;原 refreshTokenWithClientID 重构为薄封装转调新的 refreshTokenWithIdentity,行为不变。身份一致性关乎 Codex 识别(协议/凭据刷新),属核心协议机制的正确性增强。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: new RefreshTokenWithIdentity L90-L102 + refreshTokenWithIdentity L104-L138; canonical identity now resolved once and passed down (L86-L87).", - "Guard: only overrides when both UA and originator are non-empty (L98-L100); clientID trimmed with openai.ClientID fallback; no secrets logged (errors carry status/body only).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/ops_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "b4d181d9e712884ffc7f3076d482705646740831a9dc05b816289aaab23592f9", - "review_fingerprint": "b4d181d9e712884ffc7f3076d482705646740831a9dc05b816289aaab23592f9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "运维日志仓储(原生 SQL):错误日志单条/批量插入、列表(含 recovered upstream 行的可见性门与 cyber_policy 豁免)、详情、解决状态更新、系统日志批量插入/列表/清理与审计。下游相对上游把 BatchInsertSystemLogs 从 pq.CopyIn 换成 postgresBatchInsert 单条多行 INSERT(原子),并把 buildOpsErrorLogsWhere 里 StatusCodes/known/ErrorPhasesAny/ErrorTypesAny 的 ANY($n) 从 pq.Array 改为直接传切片。BatchInsertErrorLogs 仍用 prepared-stmt 事务(未改,pgx 兼容)。宿主可观测/运维机制持久层;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Delta vs aea725f: BatchInsertSystemLogs uses postgresBatchInsert L643-L685; pq.Array removed at L939,L944,L993,L997.", - "List error-log visibility gate: status>=400 OR cyber_policy unless caller opts into recovered upstream/account_auth rows (L876-L878, opsFilterIncludesRecoveredProviderRows L1004-L1024); cleanup requires >=1 constraint (L811-L813).", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/ops_write_pressure_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5c36dc36fa5d416c32199f06f9920d61aa6f0c8fd0f9d054a293cebaffa383b4", - "review_fingerprint": "5c36dc36fa5d416c32199f06f9920d61aa6f0c8fd0f9d054a293cebaffa383b4", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "集成测试(//go:build integration,直连 integrationDB 真库):既有错误日志批量插入与 scheduler outbox 去重/合并/在途放行/不同载荷不去重断言。下游相对上游新增 TestPGXBatchInsertAuditAndSystemLogs——证明迁移到 postgresBatchInsert 后 AuditLog.BatchInsert 与 Ops.BatchInsertSystemLogs 跳过 nil 条目、各写入 1 行并可查回,锁定 pq.CopyIn→pgx 批量插入迁移的行为等价。DSN 门禁在 integration_harness_test.go(TestMain 用显式 DSN 或 testcontainers,pgx/v5 驱动);t.Cleanup 按 request_id 精确清理,不 TRUNCATE 共享表。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S07-repo-rest-1-review.json", - "Downstream delta = new test L48-L96: nil-skipping batch insert for audit_logs + ops_system_logs, count-back verification, request_id-scoped cleanup.", - "Guards real DB via integrationDB (harness TestMain); existing outbox dedup/coalesce tests unchanged.", - "Static read only; no test/build execution, no DB or network access, no production behavior verified." - ] - }, - { - "path": "backend/internal/repository/passkey_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "86405d2ee5d5bdb0cc983a0e2963929da702639ef07262c919df73ce18645009", - "review_fingerprint": "86405d2ee5d5bdb0cc983a0e2963929da702639ef07262c919df73ce18645009", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Passkey(WebAuthn)凭据与 user_handle 的 PostgreSQL 仓储,属宿主通用认证的数据层。下游相对上游 aea725f 仅把唯一键冲突检测从 lib/pq 的 *pq.Error 换成 pgx/v5 的 *pgconn.PgError(code 23505 -> service.ErrPasskeyExists,L140-L143),配合下游整体切换到 pgx stdlib 驱动(postgres_driver.go);所有读写均按 user_id 约束。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta vs aea725f: only import swap lib/pq -> jackc/pgx/v5/pgconn and Create()'s unique-violation mapping (L140-L143); all queries (EnsureUserHandle/GetUserHandle/GetByCredentialID/ListByUserID/Create/UpdateCredential/Rename/Delete) unchanged and scoped by user_id.", - "Call chain: NewPasskeyRepository -> service.PasskeyRepository; error mapping consistent with the pgx driver registered in postgres_driver.go (stdlib.GetConnector); rg shows remaining lib/pq references only in ent.go/group_repo.go/setup.go outside this slice.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/repository/pgx_sqlmock_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b2f096e534b0e4c68a0c2f3e925d1e5a47b629865cc8f035c6b706c60ff14937", - "review_fingerprint": "b2f096e534b0e4c68a0c2f3e925d1e5a47b629865cc8f035c6b706c60ff14937", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "测试专用 ValueConverter:模仿 pgx/stdlib 对非 []byte 切片参数的原生透传,使 go-sqlmock 不在期望匹配前拒绝 PostgreSQL 数组参数。是下游 pgx 驱动迁移的测试基础设施,无业务规则、无断言。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "18 lines, one type pgxSQLMockValueConverter with ConvertValue (L12-L18): slices with non-uint8 elements pass through, everything else defers to driver.DefaultParameterConverter.", - "Call chain: used via sqlmock.ValueConverterOption in at least account_repo_codex_fingerprint_seed_test.go, account_repo_upstream_billing_probe_update_test.go, cindy_balance_probe_repo_test.go, channel_monitor_template_duplicate_metadata_unit_test.go, account_repo_temp_unsched_test.go (rg).", - "Test-only helper compiled only into the test binary; no runtime executor. Not executed here." - ] - }, - { - "path": "backend/internal/repository/plugin_bootstrap_update_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "88864b1eee24a1df473371d161e9e7ed5d1bbdb72b844d052a37da4a396b75d3", - "review_fingerprint": "88864b1eee24a1df473371d161e9e7ed5d1bbdb72b844d052a37da4a396b75d3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New targeted PostgreSQL tests reproduce the old API interleavings, preserve preexisting durable updating state against late Prepare/Complete, prove new Stage admission rejects unfinished bundled intent without mutation, allow normal initial Import/Complete then Stage, and cover interrupted disable, completed disable, removal and pinned ownership. Seven green leaf cases actually ran.", - "evidence": [ - "artifacts/evidence/v027-astra-bootstrap-update-review.json: confirmed API interleavings, exact red/green RUN/PASS, bounded file conclusions and explicit pending scope" - ] - }, - { - "path": "backend/internal/repository/plugin_bundle.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "364abf312083c0c52964074189c8101464b2372b3b2c690d0f1887b4b959378f", - "review_fingerprint": "364abf312083c0c52964074189c8101464b2372b3b2c690d0f1887b4b959378f", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/plugin_bundle_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "baaa6b1f2a0daa5c2a60a81d19d7cddcba95a1f3524c9ef09cabfdeaeb2ab018", - "review_fingerprint": "baaa6b1f2a0daa5c2a60a81d19d7cddcba95a1f3524c9ef09cabfdeaeb2ab018", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "插件捆绑包安装/升级日志(journal)语义的集成测试(//go:build integration,新增于下游)。四个用例证明:中断的 Prepare 恢复时不重置激活选择也不覆盖首个配置;显式删除在后续 bundle 升级中不复活(BundleApplied=true);升级保留每能力启用位与灰度百分比、新能力默认关闭、部分迁移期间所有绑定禁用且状态 CAS 违例返回 ErrPluginStateChanged;显式停用在 Complete 后仍为禁用;legacy codex ticket 导入不复活已 stopped 的 ticket(phase 保持 stopped、next_attempt_at 为 nil)。被测对象是宿主扩展注册表机制(plugin_bundle.go/plugin_legacy_import.go),非插件业务。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Asserted behaviors anchored at TestPluginBundleResumesWithoutResettingActivationOrReinstallingRemovedPlugin (L32-L61), TestPluginBundleUpgradePreservesPerCapabilityChoicesAndRollout (L63-L108, incl. require.ErrorIs ErrPluginStateChanged L90), TestPluginBundlePendingMigrationRespectsAnExplicitDisable (L110-L124), TestPluginBundleDoesNotResurrectStoppedTicketWhenLegacyRowsChange (L126-L158).", - "Call chain: pluginRepository.PrepareBundledPlugin/CompleteBundledPlugin/BundleApplied live in plugin_bundle.go; ImportLegacyPluginState in plugin_legacy_import.go; state read back via ReadExtensionState namespace 'tickets'.", - "Fixtures cleaned per test via t.Cleanup deletes on sub2api_plugin_* tables and accounts/scheduler_outbox. Statically read only; integration tag not executed." - ] - }, - { - "path": "backend/internal/repository/plugin_config_receipt_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b892d44e8fe2c1bd312146ac8bcbd6929e656c44b75e780aef187b527ae7cf53", - "review_fingerprint": "b892d44e8fe2c1bd312146ac8bcbd6929e656c44b75e780aef187b527ae7cf53", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New real PostgreSQL tests show a first write receipt never borrows a later administrator revision, old draft/package writes fail, identical cipher compares successfully without inflating revision, and stale Delete revision/package cannot remove the installation. Correct Delete still commits through graphTx.", - "evidence": [ - "artifacts/evidence/v027-astra-plugin-precondition-review.json: read/write receipt protocol, HTTP/Frame/API targeted outcomes and shared-file boundaries" - ] - }, - { - "path": "backend/internal/repository/plugin_contract_fixture_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "94821d974865d0301a2555976d72c0bc05d6da09ecaa62c97ceffeb75626bc69", - "review_fingerprint": "94821d974865d0301a2555976d72c0bc05d6da09ecaa62c97ceffeb75626bc69", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "5 行测试粘合:在 repository 测试包 init 时调用 testextensions.Install(),把进程内测试扩展目录注册进 service.ConfigureProcessExtensionServices,使本包的插件契约/捆绑测试有可用的扩展宿主。无业务规则。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Whole file is init(){ testextensions.Install() } (L5); testextensions.Install defined at backend/internal/testextensions/fixtures.go:74 wrapping service.ConfigureProcessExtensionServices(catalog.New(), operations{}).", - "Bridge-test glue per guide's adapter definition; no assertions of its own.", - "Not executed; statically read only." - ] - }, - { - "path": "backend/internal/repository/plugin_extension_state.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "275bec4c77467d940de99d62748898d8905419a2a92fd4cff32e554d62218376", - "review_fingerprint": "275bec4c77467d940de99d62748898d8905419a2a92fd4cff32e554d62218376", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/plugin_extension_state_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "08d7d97dd5254e14313a93cfbe3352552b0cd0fd2d21373b46f6d74650ac371b", - "review_fingerprint": "08d7d97dd5254e14313a93cfbe3352552b0cd0fd2d21373b46f6d74650ac371b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Fully inspected state/projection atomicity, unchanged operator account status, stale owner identity rejection, lease-generation stale-release protection and target-only job cancellation assertions. This source was reviewed, not rerun as a broad safety suite.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Source inspection is not represented as an executed test." - ] - }, - { - "path": "backend/internal/repository/plugin_host_io_admission_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4d14dca04412ea51e0618c14c7f832aed57787ca84be18ae78eeb06695ea7c8e", - "review_fingerprint": "4d14dca04412ea51e0618c14c7f832aed57787ca84be18ae78eeb06695ea7c8e", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/plugin_install_guard_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "47168a9b61e4d1f0befd88f5bcbcb9faa306f6755ba1ce007b8da3f7c0e01e79", - "review_fingerprint": "47168a9b61e4d1f0befd88f5bcbcb9faa306f6755ba1ce007b8da3f7c0e01e79", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New actual-PG regressions prove existing disabled identity cannot be replaced while a runtime lease remains or after it releases, same-version altered bytes cannot bypass updates, pending artifact and target metadata survive conflict, and explicit delete/new-ID install clears the removal intent without deleting the namespaced diagnostic ledger. All three functions actually ran and passed.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Actual targeted execution is recorded in verification below." - ] - }, - { - "path": "backend/internal/repository/plugin_legacy_import.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "adfc1093b86e5735c6bbb2a0bf49c0929c10c491eb67986092241747078b0f0c", - "review_fingerprint": "adfc1093b86e5735c6bbb2a0bf49c0929c10c491eb67986092241747078b0f0c", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "一次性 legacy 状态导入适配器(文件头注释明确 cutover 后生命周期决策在插件内运行)。ImportLegacyPluginState 以 sub2api_plugin_bootstrap.state_imported 为幂等闸(由 CompleteBundledPlugin 置 true),仅处理 codex-tickets-v1 档案:把 accounts.extra 中的 turn ticket 与 openai_codex_ticket_runtime 行映射为扩展状态(namespace tickets,key=accountID.sha256(model)),带 identity 不匹配/异常 phase 归 stopped、ticket 格式(gAAAAA 前缀、长度 292)与 account/model/identity 绑定校验,并生成调度约束与观察投影经 CompareSwapExtensionState 写入;另迁移代理信任证书到 proxy-trust 命名空间。是宿主到 codex-runtime 插件的表示迁移,不是运行期第二执行器。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Anchors: state_imported gate L23-L29; profile allowlist L30-L35 (cindy-provider-v1/image-tools-v1/admin-observability-v1 are state-free no-ops, unknown profiles error); account scan L43-L68 filters deleted_at IS NULL, platform='openai', type oauth/setup-token, parent_account_id IS NULL; importLegacyTicket L82-L151 (identity/phase sanitization L106-L110, ticket binding checks L112-L116, constraint/observation projection L138-L149); importLegacyProxyTrust L153-L173 rehashes proxy key from generation-scoped to generation-free.", - "Call chain: service/plugin_bundle.go:188 invokes store.ImportLegacyPluginState during bundle sync; CompleteBundledPlugin (plugin_bundle.go:193) sets completed+state_imported; helpers scanTicketState/ticketStateColumns/ticketFromAccount in account_repo_codex_lifecycle.go.", - "Ticket-format constants here are import-time representation mapping bound to the actual account identity (service.CodexTicketAccountIdentity); runtime lifecycle stays in the codex-runtime plugin — no duplicated executor claimed.", - "New downstream (no upstream blob); statically reviewed only." - ] - }, - { - "path": "backend/internal/repository/plugin_registry_atomicity_design_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "661d4035786777fa0fb099ff86edcdf5afb067014d52f004821729d828717858", - "review_fingerprint": "661d4035786777fa0fb099ff86edcdf5afb067014d52f004821729d828717858", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Design probe file fully read. A channel barrier pauses real Manager.Disable after its dependency preflight, then actual Commit promotes a new dependency before Disable writes. Additional explicitly test-only two-open-transaction models establish RC write skew, SSI conflict prevention, mixed-version failure and failure of transaction-external reads. Scheduling is deterministic via channels/call order, with no sleeps or stress loops. The original RC invariant red test was renamed into an explicit negative control after confirmation.", - "evidence": [ - "artifacts/evidence/v027-astra-registry-atomicity-design.json: all-writer matrix, selected SSI proof/limits, controlled PG red/green and exact targeted commands" - ] - }, - { - "path": "backend/internal/repository/plugin_registry_tx.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "e698f9dc45601d7bcad0d04f0220a810b63d0f1222722a0e2637efa70e3d333e", - "review_fingerprint": "e698f9dc45601d7bcad0d04f0220a810b63d0f1222722a0e2637efa70e3d333e", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/plugin_registry_tx_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0d91346e8d802999217a9e2d2f443b279abb34df098f115bd12990e040893707", - "review_fingerprint": "0d91346e8d802999217a9e2d2f443b279abb34df098f115bd12990e040893707", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Production-helper and actual repository tests fully read. They prove one of two overlapping graph writers aborts, binding/install validation rolls back identity/intent, promotion rejection preserves pending/config/bootstrap state and can retry after dependency restoration, Prepare/Complete roll back invalid final graphs, fault-state providers retain desired graph membership, all seven first-party bundle entries initialize in actual source order and invalid disable rolls back owned-job cancellation. Nine leaf cases ran.", - "evidence": [ - "artifacts/evidence/v027-astra-registry-atomicity-design.json: all-writer matrix, selected SSI proof/limits, controlled PG red/green and exact targeted commands" - ] - }, - { - "path": "backend/internal/repository/plugin_registry_tx_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "20efecbc07a0bce1d091b7401444232a31b3a9302b94fc7d63cc457935023fb6", - "review_fingerprint": "20efecbc07a0bce1d091b7401444232a31b3a9302b94fc7d63cc457935023fb6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Unit test fully read and executed. Direct/wrapped PostgreSQL 40001 maps to the established retryable target conflict, while the existing conflict, unrelated constraint error and nil remain distinct; no implicit arbitrary retry classification is introduced.", - "evidence": [ - "artifacts/evidence/v027-astra-registry-atomicity-design.json: all-writer matrix, selected SSI proof/limits, controlled PG red/green and exact targeted commands" - ] - }, - { - "path": "backend/internal/repository/plugin_repo.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "ea9770a26744227a994d24ac9ae096376661a1ff3ddc7dbac3a361eec2b747c6", - "review_fingerprint": "ea9770a26744227a994d24ac9ae096376661a1ff3ddc7dbac3a361eec2b747c6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Full repository previously inspected and current receipt/Delete diff reviewed. Added UpdateConfigReturningRevision using a single UPDATE with revision/binary/package/updating CAS and RETURNING revision; old UpdateConfig wraps it. Delete adds revision/package predicates while retaining the prior graph transaction. All other SSI/graph entry changes belong to the frozen prior round, not new edits here.", - "evidence": [ - "artifacts/evidence/v027-astra-plugin-precondition-review.json: read/write receipt protocol, HTTP/Frame/API targeted outcomes and shared-file boundaries" - ] - }, - { - "path": "backend/internal/repository/plugin_repo_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "352af4b29a6ac2b3e37d61a62c2808551591eb5779a55f3930d9881228f4cd45", - "review_fingerprint": "352af4b29a6ac2b3e37d61a62c2808551591eb5779a55f3930d9881228f4cd45", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Lifecycle fixture now expects a typed existing-identity conflict both before and after disable. It permits reinstall only after explicit Delete and checks the new installation ID plus binary-digest delete fence. This changed fixture compiled with targeted PG tests but its test function was not executed again; the new dedicated install tests cover the changed create-only contract.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Source inspection is not represented as an executed test." - ] - }, - { - "path": "backend/internal/repository/plugin_runtime_lease_loss_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0b3dd0aca2e9dc27801863f9b4ae47ba7d9556c00355fd08f1b8b08a59a1f18f", - "review_fingerprint": "0b3dd0aca2e9dc27801863f9b4ae47ba7d9556c00355fd08f1b8b08a59a1f18f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New local-PG diagnostic/regression source completely read. Termination is gated to one exact disposable DB, loopback address and port; captured session PIDs are rechecked against DB/current role/application_name at termination. Baseline shows advisory release can precede caller cancellation while durable domain lease/state fences remain. Strong-port test observes loss, successful cleanup and normal-release semantics without reconnect; it explicitly records commit may precede notification.", - "evidence": [ - "artifacts/evidence/v027-astra-runtime-lease-loss-review.json: isolated observed window, exact targeted RUN/PASS, detector/cancellation and normal-release invariants, explicit guarantee limits" - ] - }, - { - "path": "backend/internal/repository/plugin_runtime_lease_monitor_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0c88e330f6afa46288c726b272327dba27b0390bef7c8d41221ab25870c39225", - "review_fingerprint": "0c88e330f6afa46288c726b272327dba27b0390bef7c8d41221ab25870c39225", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New internal-session fixture implements both Ping and Close. Deterministic short-clock tests prove normal Release cancels a blocked probe without concurrent Close, notification-triggered Release cannot deadlock the monitor, and timeout is loss with no retry/reconnect. All three cases ran.", - "evidence": [ - "artifacts/evidence/v027-astra-runtime-lease-loss-review.json: isolated observed window, exact targeted RUN/PASS, detector/cancellation and normal-release invariants, explicit guarantee limits" - ] - }, - { - "path": "backend/internal/repository/plugin_update.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "e61641c705172113b8a989f041ebfe58ce35487e7f3118042b78de609f25877f", - "review_fingerprint": "e61641c705172113b8a989f041ebfe58ce35487e7f3118042b78de609f25877f", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/plugin_update_integration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3df59c02e7fe29e5dece0b7d5f22a64580ea3ae31305a7c8637647ef1a304444", - "review_fingerprint": "3df59c02e7fe29e5dece0b7d5f22a64580ea3ae31305a7c8637647ef1a304444", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/postgres_batch_insert.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "05762a5edbbcbb207e547e64db6f1dd18df634c1398ba086062f2dc026e83595", - "review_fingerprint": "05762a5edbbcbb207e547e64db6f1dd18df634c1398ba086062f2dc026e83595", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增的通用单语句多行 INSERT 助手:pgx.Identifier.Sanitize 处理表/列名,行数超过 65535/len(columns) 绑定参数上限即拒绝,逐行校验列数,执行后要求 RowsAffected 恰等于行数否则报错。无业务语义,调用方为审计日志与运维日志仓储。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Anchors: bind parameter cap L32-L34; identifier sanitization L38/L47; per-row arity check L54-L56; affected-count verification L81-L83.", - "Call chain (rg): audit_log_repo.go:81 (audit_logs) and ops_repo.go:685 (ops_system_logs) are the only non-test callers.", - "New downstream file; whole file is the delta. Statically reviewed only." - ] - }, - { - "path": "backend/internal/repository/postgres_batch_insert_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8ef6f61ddef79756e33554108790a0064cf1ada3e5686e21160dadff03ac1e6e", - "review_fingerprint": "8ef6f61ddef79756e33554108790a0064cf1ada3e5686e21160dadff03ac1e6e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "postgresBatchInsert 的 sqlmock 单元测试:证明两行批量生成单条带编号占位符的 INSERT 且参数展开有序;列数不符在执行前被拒绝(sqlmock 无期望即证明未触库);RowsAffected 与行数不符返回错误。测试对象是核心数据层机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Assertions: TestPostgresBatchInsertBuildsAtomicMultiRowStatement L11-L30 (exact SQL regex + args + affected 2); TestPostgresBatchInsertRejectsInvalidRowsBeforeExecution L32-L47 ('has 1 values, want 2', ExpectationsWereMet proves no exec); TestPostgresBatchInsertRejectsUnexpectedAffectedCount L49-L67.", - "Subject is core repository mechanism (postgres_batch_insert.go), not a plugin.", - "Statically read; not executed." - ] - }, - { - "path": "backend/internal/repository/postgres_driver.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e784f9634e9b1ba0c88e26111b307be9b3f4b77809a73ad7bf4e7f3ea6039366", - "review_fingerprint": "e784f9634e9b1ba0c88e26111b307be9b3f4b77809a73ad7bf4e7f3ea6039366", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增:用 pgx/v5 stdlib connector 打开 database/sql 连接池(OpenPostgresDB/openPostgresDB),可选包一层 server-timing connector 用于观测。替代上游的 lib/pq DSN 打开方式,属核心数据层驱动机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Anchors: pgx.ParseConfig + stdlib.GetConnector L16-L21; enableServerTiming wraps with newServerTimingConnector (defined in server_timing_sql.go:18) L22-L24.", - "Call chain (rg): ent.go:117 calls openPostgresDB(dsn, cfg.Server.EnableServerTiming); isPostgresDriver (dashboard_aggregation_repo.go:49) detects the pgx driver.", - "New downstream file; whole file is the delta. Statically reviewed only." - ] - }, - { - "path": "backend/internal/repository/postgres_driver_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6d21b94007b9e64b4d9a0ac74ee9c9e76f96dff865b76ddcf56246a02cb1092b", - "review_fingerprint": "6d21b94007b9e64b4d9a0ac74ee9c9e76f96dff865b76ddcf56246a02cb1092b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "驱动注册单元测试:证明 sql.Drivers() 含 pgx/v5、sql.Open 惰性打开不报错,且 openPostgresDB 在开/关 server-timing 两种情况下都仍被 isPostgresDriver 识别为 pgx 驱动(防止包装 connector 丢失驱动特征)。sql.Open/OpenDB 均为惰性、不建立连接,故为纯单元测试。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Assertions: TestPGXMajorVersionDriverIsRegistered L10-L27; TestOpenPostgresDBPreservesPGXDriverWithServerTiming L29-L43 iterating enableServerTiming false/true.", - "Subject: postgres_driver.go + isPostgresDriver (dashboard_aggregation_repo.go); DSN constant points at localhost but no query is issued (lazy open), so no network at test definition level.", - "Statically read; not executed." - ] - }, - { - "path": "backend/internal/repository/public_model_retirement_migration_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "efea72c2239b8d03a235af135c40089e1ec8e77cfd5a13f68daa21fb53c22754", - "review_fingerprint": "efea72c2239b8d03a235af135c40089e1ec8e77cfd5a13f68daa21fb53c22754", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "迁移 242_retire_public_model_manager.sql 的集成测试(integration tag)。fixture 先重放 240 旧 schema 并按计划摘要(group/channel/credentials 的 sha256)写入 public_model_retirement_plan;用例一证明清退迁移把合成 s2pub-* 映射改写为真实模型映射且保留大小写敏感的私有映射、api_key、schedulable、费率乘数、余额、actual_cost、api_key 分组,删除 admin_capability_* 三表与两个 settings 键,且重放幂等;用例二证明计划外漂移(rate_multiplier 被改)时迁移以 public_retirement_group_changed 中止且无部分清理(SAVEPOINT 回滚后合成映射与表均在)。证明的是下游数据迁移的安全性。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Anchors: fixture digest computation L46-L48 and plan document L49-L59; preservation assertions L70-L91; idempotent replay L92-L94; drift abort L97-L114 (require.ErrorContains 'public_retirement_group_changed', post-rollback intact checks).", - "Subject: migrations/242_retire_public_model_manager.sql via dbmigrations.FS; runs inside testTx so each case is transaction-scoped.", - "Statically read; integration tag not executed; no database contacted by this review." - ] - }, - { - "path": "backend/internal/repository/quota_activity.go", - "candidate_owner": "core-quota-and-protocol", - "role": "source", - "present": true, - "content_sha256": "6ecc57deae3303b865847fb37eccb1e3638134be5c09aa62219d4d9ad46d751d", - "review_fingerprint": "6ecc57deae3303b865847fb37eccb1e3638134be5c09aa62219d4d9ad46d751d", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Redis Lua state tracks active observations, 90-second expiry gaps, revision, and epoch atomically; epoch changes and abandoned requests invalidate calibration reads.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=6ecc57deae3303b865847fb37eccb1e3638134be5c09aa62219d4d9ad46d751d; current_sha256=6ecc57deae3303b865847fb37eccb1e3638134be5c09aa62219d4d9ad46d751d; inventory_sha256_match=true", - "lines 19-39: atomic active/revision/gaps/epoch script", - "lines 41-65: strict stamp type validation", - "lines 67-80: Begin/Refresh/Finish/Read store operations" - ] - }, - { - "path": "backend/internal/repository/quota_activity_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f1dba9df33ac7f28e415605162e11eb1bfba51cf2d6532f4ec597db71801565c", - "review_fingerprint": "f1dba9df33ac7f28e415605162e11eb1bfba51cf2d6532f4ec597db71801565c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static test source covers expiry gap accounting and Redis epoch replacement; test execution was not repeated.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=f1dba9df33ac7f28e415605162e11eb1bfba51cf2d6532f4ec597db71801565c; current_sha256=f1dba9df33ac7f28e415605162e11eb1bfba51cf2d6532f4ec597db71801565c; inventory_sha256_match=true", - "TestQuotaActivityClockDetectsExpiredWorkAndRedisEpochChanges", - "lines 21-42: abandoned work increments gaps and FlushAll changes epoch" - ] - }, - { - "path": "backend/internal/repository/remote_skill_job_expiry_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bdf8a630839c80d9b030f24be59a5d1c8f30b09007815d27028fc109b4c41d12", - "review_fingerprint": "bdf8a630839c80d9b030f24be59a5d1c8f30b09007815d27028fc109b4c41d12", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/remote_skill_registry_repository.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "8db421b14492cde0eaf2d42c6f2700bae20cccab4f8046133ef30446074b5b1c", - "review_fingerprint": "8db421b14492cde0eaf2d42c6f2700bae20cccab4f8046133ef30446074b5b1c", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/remote_skill_registry_repository_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "441b8de2e560674b1daf07641580d7d1cf5909a37dbf972edf4ba5a6eb84f1af", - "review_fingerprint": "441b8de2e560674b1daf07641580d7d1cf5909a37dbf972edf4ba5a6eb84f1af", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/remote_skill_registry_revision_bus.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "9070f48ec57f9bc27a242a97f61cd80e15e9ca54192de087dd5b484f714d6e44", - "review_fingerprint": "9070f48ec57f9bc27a242a97f61cd80e15e9ca54192de087dd5b484f714d6e44", - "review_status": "pending" - }, - { - "path": "backend/internal/repository/scheduler_cache.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e185ced9ed6f2ff4939bfd3aa0604b3381677354057e8efa58b458dac78854e5", - "review_fingerprint": "e185ced9ed6f2ff4939bfd3aa0604b3381677354057e8efa58b458dac78854e5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "调度器 Redis 快照缓存(epoch/retired 双闸 fencing、版本 CAS 激活、宽限期 EXPIRE)。下游相对上游:meta/ready/active/ver/快照键升代到 v2 前缀并在 retire/reopen/activate Lua 与 DeleteAccount/UpdateLastUsed 中同步删除 legacy 键,防止凭据轮换后旧 sched:meta: 长期可读;writeAccountIDs 从 Pipeline 改 TxPipeline 保证分块原子发布,不可编码账号改为清删其四个缓存键而非仅跳过;元数据投影新增 WirePlatform/ProviderProfile、credentials 白名单加 base_url/openai_capabilities,extra 白名单加 reasoning replay/signature recovery(present-but-malformed 按 fail-closed 投影为 false)、request_integrity_mode、Codex 客户端身份与 5h/7d/primary/secondary 用量窗口键、openai_quota_*、PluginAccountProjectionKey(插件调度投影透传)及上游计费探针子过滤。投影刻意排除凭据绑定的 ticket/身份材料(注释 L916-L920)。全部为宿主调度缓存机制,插件数据仅作透明投影,无第二执行器。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta anchors vs aea725f: v2 key constants + legacy prefixes L17-L31; retire/reopen scripts also DEL the legacy ready key (retire L124, reopen L132) and activate script DELs KEYS[7] legacy ready (L217); schedulerBucketKey/schedulerSnapshotKeyPrefix now use bucket.String() L723-L737; DeleteAccount adds legacy meta key L610-L622; UpdateLastUsed unencodable path deletes 4 keys L646-L661; writeAccountIDs TxPipeline + delete-on-unencodable L807-L878; projection additions L921-L1143 incl. fail-closed reasoning-policy handling L1119-L1128 and filterSchedulerUpstreamBillingProbe L1146-L1184.", - "Call chain: NewSchedulerCache -> service.SchedulerCache; SetSnapshotAndReturnAccountIDs/SetSnapshotByAccountIDs consumed by service/scheduler_snapshot_service.go:1027-1033 for same-batch bucket reuse; PluginAccountProjectionKey read by service/plugin_scheduling.go:91; reasoning keys consumed by service/account.go IsOpenAIChatReasoningReplayEnabled/IsOpenAIReasoningSignatureRecoveryEnabled.", - "Boundary: TryLockBucket/UnlockBucket without owner token is inherited upstream behavior (unchanged in diff) and is backstopped by the epoch/version fencing; not claimed as a downstream defect.", - "Statically reviewed only; Lua scripts read, no Redis contacted." - ] - }, - { - "path": "backend/internal/repository/scheduler_cache_reasoning_policy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f6eaf6f99628d4c1ca92272e16c0602f7384e8b7a1341788a1a8c20025344ead", - "review_fingerprint": "f6eaf6f99628d4c1ca92272e16c0602f7384e8b7a1341788a1a8c20025344ead", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "unit 标签测试,证明 filterSchedulerExtra 对两个 reasoning 策略键的下游修复语义:键缺失不进投影(保持默认启用);present-but-malformed(nil/字符串/数字/切片/映射)一律投影为 false(fail-closed)且不改写源 map;marshal/decode 元数据往返后 Account 的两个策略 getter 与源一致(覆盖 openai/cindy/grok 多平台与父子账号);策略键变更会触发既有的 scheduler outbox 失效入队。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Assertions: projection semantics L13-L40 (absence L15-L20, fail-closed matrix L21-L38, source non-mutation L32); round-trip getter equality L42-L69 via marshalSchedulerCacheAccount/decodeCachedAccount; outbox invalidation L71-L77 via shouldEnqueueSchedulerOutboxForExtraUpdates.", - "Subject is the core scheduler cache projection fix in scheduler_cache.go L1119-L1128; proves the downstream fail-closed change.", - "Statically read; not executed." - ] - }, - { - "path": "backend/internal/repository/scheduler_cache_unit_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e93a459a47253ccc632417010d93413258b3661e530bce0d8de7bc3f512756b3", - "review_fingerprint": "e93a459a47253ccc632417010d93413258b3661e530bce0d8de7bc3f512756b3", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "调度缓存 miniredis 单测套件(unit 标签,1356 行)。下游相对上游新增:三个 v2 代际隔离测试(v2 reader 忽略 legacy ready/active/快照与 sched:meta:,SetAccount/DeleteAccount/UpdateLastUsed/writeAccountIDs 清除 legacy 凭据副本,v2 激活删 legacy ready 但不改 legacy active 指针)、既有不可编码用例补 legacy 键断言、KeepsCindyRoutingIdentity(base_url/openai_capabilities 进投影而 header_overrides/access_token/refresh_token 被裁掉,WirePlatform/ProviderProfile 往返保留)。存量部分证明 ID 复用发布与完整发布 payload 一致且不复活已删账号、空快照回源、retire/reopen 幂等与 epoch fencing(含宽限 TTL 到期)、组生命周期租约单持有者/过期释放丢失/跨组拒绝/取消上下文 fail-closed、透传开关投影守护(#4936 输入面)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "New-vs-upstream anchors (git diff): TestSchedulerCacheIgnoresLegacyMetadataGeneration L36-L85, TestSchedulerCacheMetadataGenerationCleansLegacyCredentialCopies L87-L116, TestSchedulerCacheV2ActivationKeepsLegacyReaderGenerationConsistent L118-L177, legacy-key assertions added in L183/L199/L208/L217/L225/L233, TestBuildSchedulerMetadataAccount_KeepsCindyRoutingIdentity L733-L815.", - "Pre-existing coverage read in full: snapshot ID reuse L236-L415, fencing/retire/reopen L817-L1020, lifecycle lease L1022-L1191, payload benchmark L1193-L1314, passthrough projection guard L1316-L1356.", - "Subject is core scheduler cache (scheduler_cache.go); Cindy/codex keys appear only as projected data. Tests use miniredis in-process; statically read here, not executed." - ] - }, - { - "path": "backend/internal/repository/temp_unsched_cache.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a7da779e58bb769cdd16039d31eb08b56bcb24547d555cd059b7d0751b17b9e6", - "review_fingerprint": "a7da779e58bb769cdd16039d31eb08b56bcb24547d555cd059b7d0751b17b9e6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "临时不可调度状态的 Redis 缓存(只延长不缩短的 SetTempUnsched Lua、OpenAI APIKey 健康滚动窗口计数)。下游相对上游新增守护式清理:GetTempUnschedSnapshot 同一次 GET 返回解析结构与原始字节,DeleteTempUnschedIfMatch 用整值 CAS Lua 只删除 DB CAS 前读到的原值(无快照不退回无条件删除),并断言实现 service.TempUnschedGuardedCache。防止延迟清理误删同截止秒重建的新载荷。通用调度机制,无插件业务。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta anchors vs aea725f: tempUnschedDeleteIfMatchScript L60-L66, GetTempUnsched refactored onto GetTempUnschedSnapshot L100-L120, DeleteTempUnschedIfMatch L128-L139, interface assertion L141.", - "Call chain: service/temp_unsched.go:45-50 defines TempUnschedGuardedCache (snapshot before DB CAS, guarded delete after); health failure script unchanged upstream content (hash-tagged key for cluster slot, L143-L147).", - "Statically reviewed only; no Redis contacted." - ] - }, - { - "path": "backend/internal/repository/temp_unsched_cache_health_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6c4857851a101bd452cd827484fe07a66222349af2c4392bf5f438c75bcf15eb", - "review_fingerprint": "6c4857851a101bd452cd827484fe07a66222349af2c4392bf5f438c75bcf15eb", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "miniredis 单测:前两个用例(上游已有)证明健康失败计数在滚动窗口内第 threshold 次触发熔断、窗口外旧失败被剔除;下游新增 TestTempUnschedCacheDeleteIfUntilOnlyRemovesMatchingPause 证明守护删除只删匹配原值的载荷——键被删后以同一截止秒重建的替代载荷不被过期的清理删除,匹配当前值时才删除。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Assertions: trip-at-threshold L14-L28; window expiry L30-L50 (miniredis SetTime); guarded delete L52-L83 (delete+recreate with same UntilUnix, stale snapshot must not delete, current snapshot deletes).", - "Downstream delta per git diff = only the third test; subject is temp_unsched_cache.go's guarded CAS delete.", - "Statically read; not executed." - ] - }, - { - "path": "backend/internal/repository/usage_billing_owner_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "096040913fda9acd5c08a0d496fa5fa04f30796b840de18c0db853cf30479aa7", - "review_fingerprint": "096040913fda9acd5c08a0d496fa5fa04f30796b840de18c0db853cf30479aa7", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "unit 标签 sqlmock 测试:证明 Apply 的 dedup INSERT 携带 account_id(args: req-1, 7, fingerprint, 42)、RETURNING 回读 owner,首个成功账号 42 作为 OwnerAccountID 随 Applied=true 返回,且余额扣减在同一事务提交。证明下游 owner 记录链路的写入侧。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Single test TestUsageBillingApplyStoresFirstSuccessfulAccountOwner L15-L39: ExpectBegin -> INSERT INTO usage_billing_dedup WithArgs(..., int64(42)) returning (id, account_id) -> archive probe empty -> UPDATE users returning balance -> Commit.", - "Subject: usage_billing_repo.go claimUsageBillingRequestWithOwner; complements the low finding recorded there (archive path owner semantics are NOT covered by this test).", - "Statically read; not executed." - ] - }, - { - "path": "backend/internal/repository/usage_billing_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "94f62c1c8c69a1c65fc4ceeae90f9a8a25d6386dc35ac57031650f5a0abea864", - "review_fingerprint": "94f62c1c8c69a1c65fc4ceeae90f9a8a25d6386dc35ac57031650f5a0abea864", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "用量计费仓储:request_id+api_key_id 去重表 claim(含指纹冲突与归档表复查)、订阅/余额/APIKey 配额/速率窗口/账号配额的事务化递增、批量生图余额冻结-结算-释放(含防幻影释放校验)。下游相对上游:dedup 行新增 account_id(NULLIF($4,0)),Apply 在首次与重复两种结果上都返回 OwnerAccountID(migrations/238 加列)。归档重复路径会把调用方自身账号当 owner 返回,已记 low finding(当前无生产读者,事务回滚不留脏行)。账号配额跨越限额时入队 scheduler outbox 刷新快照。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta anchors vs aea725f: claimUsageBillingKeyWithOwner/claimUsageBillingRequestWithOwner L65-L116 (INSERT account_id via NULLIF, RETURNING COALESCE(account_id,0); duplicate row returns stored owner L84-L95); Apply result carries OwnerAccountID L45-L53.", - "Unchanged upstream logic read in full: batch image hold/capture/release incl. phantom-release guard batchImageHoldClaimExists L340-L404, balance deduct with overdraft fallback L249-L279, api key quota/rate-limit windows L422-L471, account quota jsonb increment + outbox on limit crossing L473-L565.", - "Finding recorded (low): archive-duplicate path L100-L115 echoes the retry caller's account as OwnerAccountID because usage_billing_dedup_archive stores no account_id (dashboard_aggregation_repo.go:356 archival INSERT); no production reader of OwnerAccountID yet (rg: only service struct field + tests).", - "Stale comment nit (not a finding): L544-L546 still says 'pq 驱动' after the pgx migration. Statically reviewed only." - ] - }, - { - "path": "backend/internal/repository/usage_log_repo_stats.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e3a9f9369d586a623f9e7b775d9abdb7ae5a6407ce237abfc5eaf047047ad08c", - "review_fingerprint": "e3a9f9369d586a623f9e7b775d9abdb7ae5a6407ce237abfc5eaf047047ad08c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "usage_logs 聚合统计仓储(用户/APIKey/账号/模型/全局/端点分组统计,GROUPING SETS 一次查询出总值+端点拆分,时区感知日分组)。下游相对上游两类改动:一是去掉 lib/pq 的 pq.Array(pgx 原生传数组,共 4 处批量查询);二是账号三个 today/window 统计把窗口下界钳到 accounts.cindy_account_stats_reset_at(GREATEST+COALESCE '-infinity',migrations/238 的 Cindy 专用统计水位,列为 NULL 时对其他平台零影响)。核心侧只读该水位、不写(rg:backend 内无写者,重置动作在 cindy-provider 域/运维侧),无第二执行器。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta anchors vs aea725f: pq import removed; GetAccountTodayStats L278-L288, GetAccountWindowStats L309-L319, GetAccountWindowStatsBatch L346-L358 gain LEFT JOIN accounts + GREATEST($2, COALESCE(a.cindy_account_stats_reset_at, '-infinity')); pq.Array dropped at former call sites (GetAccountWindowStatsBatch/GetGeminiUsageTotalsBatch/GetBatchUserUsageStats/GetBatchAPIKeyUsageStats).", - "Unchanged upstream logic read in full: aggregated stats L19-L183, daily grouping with app timezone L187-L272, Gemini pro/flash split L394-L445, GROUPING SETS stats with account-cost substitution L660-L828, endpoint stats builder L842-L918, account usage history/summary L921-L1101.", - "Watermark write path is absent from core by design (only migration 238 defines the column; a guard test cindy_account_stats_reset_test.go pins the SQL shape); the read is data-driven and inert when NULL — noted, not claimed as a defect.", - "Statically reviewed only; no database contacted." - ] - }, - { - "path": "backend/internal/repository/user_group_rate_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2a258e128a93cc1d5242c3e56a461da54ef3ded49cccd09c1e3ebbab539c54e3", - "review_fingerprint": "2a258e128a93cc1d5242c3e56a461da54ef3ded49cccd09c1e3ebbab539c54e3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "用户×分组专属费率与 RPM 覆盖仓储:查询(单用户/批量/按组联 users 排除软删)、SyncUserGroupRates/SyncGroupRateMultipliers/SyncGroupRPMOverrides 三个同步器都遵循『清 NULL→整行全 NULL 则删→unnest 批量 upsert』的模式,互不触动对方列。下游相对上游仅移除 pq.Array(7 处,pgx 原生数组),SQL 语义不变。属核心计费/限速数据层。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta vs aea725f: import lib/pq dropped; pq.Array removed at GetByUserIDs L68-L72, SyncUserGroupRates L202-L232, SyncGroupRateMultipliers L261-L295, SyncGroupRPMOverrides L328-L364; no logic change.", - "Full-file read: rate/rpm getters L21-L169, sync semantics with doc comments L171-L371, ClearGroupRPMOverrides/DeleteByGroupID/DeleteByUserID L373-L399; all statements scoped by user_id/group_id.", - "Statically reviewed only." - ] - }, - { - "path": "backend/internal/repository/user_platform_quota_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e537d4c01c936742f8be0445d28dbc6845191c88af2e3c8d991ed593e4ba8df9", - "review_fingerprint": "e537d4c01c936742f8be0445d28dbc6845191c88af2e3c8d991ed593e4ba8df9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "用户×平台配额仓储(T14):幂等 BulkInsertInitial(ON CONFLICT 只补 NULL 档位)、FOR UPDATE 事务内 IncrementUsageWithReset(日/周历法窗口+30 天滚动月窗)、无条件 ResetExpiredWindow(注释明确警告其不校验过期、仅供 admin 强制归零)、软删+部分唯一索引下的 UpsertForUser 并发安全 upsert、BatchSnapshotUsage 多行 VALUES 绝对值覆盖(6000 行/批、不建行不复活软删行)。下游相对上游仅在 BatchSnapshotUsage 增加 pgconn 23503 → ErrUserPlatformQuotaFKViolation 映射(pgx 驱动迁移配套;上游声明了该错误变量但无映射)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta vs aea725f: import jackc/pgx/v5/pgconn + errors.As(pgErr).Code==23503 mapping at L482-L485 only.", - "Full-file read: record/interface L16-L74, BulkInsertInitial L94-L132, window logic maybeReset/monthlyMaybeReset L297-L312, UpsertForUser + soft-delete/partial-unique-index handling L320-L419, BatchSnapshotUsage batching & known-race comments L421-L490.", - "Consumers: repository/user_platform_quota_service_adapter.go:114/210 translates the typed error to service.ErrUserPlatformQuotaFKViolation for the flusher; adapter is outside this slice.", - "Statically reviewed only." - ] - }, - { - "path": "backend/internal/repository/user_platform_quota_repo_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fba115662dcade04ec2d1ff7f9a4b743f9d523fee6c882258287e468c3d4ea6c", - "review_fingerprint": "fba115662dcade04ec2d1ff7f9a4b743f9d523fee6c882258287e468c3d4ea6c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "用户平台配额仓储的集成测试(integration tag)。存量用例证明幂等 BulkInsertInitial、累加/日重置/周重置/无行不建行、ResetExpiredWindow 只动指定窗口并返回哨兵错误、BatchSnapshotUsage 绝对覆盖且不建行不复活软删行;下游相对上游把 minimax 加入国产供应商 CHECK 约束回归用例,并新增 CindyAllowed 用例锁定 cindy 平台可写入(回归下游平台枚举扩展,防注册预填充整批 INSERT 被 CHECK 拒绝的历史 bug 复发)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Downstream delta per git diff: minimax added to TestUserPlatformQuotaRepository_BulkInsertInitial_CNProvidersAllowed L117-L141; new TestUserPlatformQuotaRepository_BulkInsertInitial_CindyAllowed L143-L161 (service.PlatformCindy).", - "Pre-existing coverage read in full: idempotent insert L38-L73, grok CHECK regression L90-L111, increment/reset semantics L193-L286, ResetExpiredWindow L288-L331, multi-row placeholder ordering L333-L370, snapshot overwrite L385-L480, no-row/soft-deleted noop L484-L525.", - "Statically read; integration tag not executed; no database contacted." - ] - }, - { - "path": "backend/internal/repository/user_repo.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0f58face3c0574b7d9ab40c302e225fe73f12d45bd5fefdb6acd46ef0d4c74c9", - "review_fingerprint": "0f58face3c0574b7d9ab40c302e225fe73f12d45bd5fefdb6acd46ef0d4c74c9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "用户仓储(1598 行):注册/更新/删除的事务化实现(邮箱归一化唯一锁、收件箱别名去重探针+LIKE 转义、注册域名额度锁、email auth identity 补写/换绑、允许分组同步)、余额原子操作(AdjustBalance/SetBalance RETURNING 旧新值、DeductAvailableBalance 退款专用不加深透支)、并发/RPM 批量更新、TOTP 管理、按属性过滤与 last_used_at 子查询排序。下游相对上游仅移除 pq.Array(GetLatestUsedAtByUserIDs、BatchSetConcurrency、BatchAddConcurrency、BatchUpdateLimits 共 4 处,pgx 原生数组),无逻辑变化。属核心用户/认证数据层。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta vs aea725f: import lib/pq dropped; pq.Array removed at L729, L1081, L1095, L1121; nothing else.", - "Full-file read anchors: create with email/alias/domain locks L65-L176, Update with conditional email lock L239-L367, auth identity ensure/replace incl. synthetic-domain skip L369-L452, delete with identity unlink L454-L519, list/filter/sort L521-L827, balance ops L829-L1037, batch limits L1072-L1134, alias probes with LIKE escaping L1140-L1287, domain count L1348-L1376, allowed-groups sync L1445-L1527, TOTP L1557-L1598.", - "All operations are bound to explicit user ids or normalized-email locks; no downstream business rule beyond the driver migration. Statically reviewed only." - ] - }, - { - "path": "backend/internal/repository/wire.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "27a555079798fac8eb1c23633e7c6b88e3d088357f4438cb29626f7ec5d6de4f", - "review_fingerprint": "27a555079798fac8eb1c23633e7c6b88e3d088357f4438cb29626f7ec5d6de4f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "repository 层的 Wire DI 汇总。下游相对上游在 ProviderSet 注册新增仓储与缓存:账号凭据身份、账号任务(+Cindy 变更 runner)、图像工作台、Cindy 余额探针/健康、QuotaActivityStore、业务系统提示词与远程技能注册表(各带 revision bus)、账号流量观察缓存,并把 NewPluginRepository 换成 ProvidePluginRepository。均为构造函数登记,不含业务逻辑;ProvideSchedulerCache/ProvideSQLDB 等提供函数与上游一致。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S08-repo-rest-2-review.json", - "Delta vs aea725f: ProviderSet additions at L74-L79 (account credential identity/jobs/cindy runner/image studio/cindy probe+health), L105-L106 (ProvidePluginRepository, NewQuotaActivityStore), L113-L116 (business system prompt + remote skill registry repos and revision buses), L130 (ProvideAccountTrafficObserveCache).", - "Full-file read: provider functions ProvideConcurrencyCache/ProvideGitHubReleaseClient/ProvidePricingRemoteClient/ProvideSessionLimitCache/ProvideSchedulerCache L18-L64, ProviderSet L67-L185, ProvideEnt/ProvideImageStorageFactory/ProvideSQLDB/ProvideRedis L194-L245.", - "Pure DI registration; the registered implementations live in their own files (reviewed under their own coverage records). Statically reviewed only." - ] - }, - { - "path": "backend/internal/securityaudit/prompt_config_integration_test.go", - "candidate_owner": "admin-observability", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f7771ec632a529720626859fdeb6613239fef1b908e67abf67971ae0cf14b60e", - "review_fingerprint": "f7771ec632a529720626859fdeb6613239fef1b908e67abf67971ae0cf14b60e", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "提示词安全审计 ConfigManager 的集成测试 (需设置 PROMPT_AUDIT_TEST_REDIS_ADDR 与 PROMPT_AUDIT_TEST_POSTGRES_DSN, 否则 Skip): 用真实 Postgres settings 表实现 SettingRepository, 验证两个 manager 经 Redis 频道同步配置版本、端点 token 以密文落库且公开 JSON/ChangeSummary 不含明文、并发 Save 的 CAS 只允许一个成功 (另一个返回 ErrorCodeConfigConflict)、无 Redis 订阅的 manager 经 5s 刷新循环收敛、Redis 发布失败不回滚已提交的 Postgres 配置。测试实质与上游 aea725f 相同; 下游唯一改动 (+1 -2) 是删除 github.com/lib/pq 导入并把 `key=ANY($1)` 的参数从 pq.Array(keys) 改为直接传 []string (配套下游把测试驱动切到 pgx/v5 stdlib, 见 prompt_repository_integration_test.go), 不证明新的下游修复, 故为 reference。仅静态阅读, 未连接任何 Redis/Postgres。", - "evidence": [ - "Full-file static review (L1-L243): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+1 -2): 删除 L18 `github.com/lib/pq` 导入; L58 QueryContext 参数 pq.Array(keys) → keys", - "被测代码: securityaudit/prompt_config_store.go ConfigManager (Save/Start/Shutdown/Reload/Active, ConfigInvalidationChannel), 不在本切片; 夹具 openPromptAuditIntegrationDB 定义于 prompt_repository_integration_test.go L23-L58", - "Integration test statically read only; not executed; no database or Redis was contacted." - ] - }, - { - "path": "backend/internal/securityaudit/prompt_event_repository.go", - "candidate_owner": "admin-observability", - "role": "source", - "present": true, - "content_sha256": "8a1cb2bf5723ba91f8f34e6c137ff836fb9375d44a222453a965e59c8ac152ff", - "review_fingerprint": "8a1cb2bf5723ba91f8f34e6c137ff836fb9375d44a222453a965e59c8ac152ff", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "提示词审计事件的 PostgreSQL 仓储: 分页列表 (页大小 1..100, 按 created_at/id 倒序)、单条详情 (仅详情加载 full_prompt)、按 ID 批量删除 (上限 500, RETURNING job_id 后删除非 processing 的孤儿 job)、按过滤条件预览 (RepeatableRead 只读事务取 COUNT 与 MAX(id) 并生成 FilterHash) 与高水位分批删除 (FOR UPDATE SKIP LOCKED, 只删 id<=快照), buildEventWhere 统一参数化 (关键字 ILIKE 共用一个占位符), scanEvent 组装 IssueSummaries。该包在上游 aea725f 已存在 (git ls-tree 有 blob), 下游相对上游仅 (+2 -4): 删除 lib/pq 导入, 两处 `ANY($1)` 参数由 pq.Array(ids)/pq.Array(jobIDs) 改为直接传 []int64, 与下游数据库驱动切换到 pgx/v5 stdlib (原生支持切片参数) 保持一致。属于宿主持久化机制; rg plugins/admin-observability 未见对 prompt_audit/securityaudit 的引用, 无插件重复执行器。仅静态阅读, 未执行任何 SQL。", - "evidence": [ - "Full-file static review (L1-L385): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+2 -4): 删除 L13-L14 `github.com/lib/pq` 导入; L128 DeleteEventsByIDs 与 L380 deleteOrphanJobs 的 ANY($1) 参数去掉 pq.Array 包装", - "anchors: ListEvents L60-L98, GetEvent L100-L106, DeleteEventsByIDs L112-L142 (500 上限 L117), PreviewDelete L144-L164, DeleteEventsByFilter L166-L219 (SKIP LOCKED CTE L178-L186), FilterHash L221-L229, buildEventWhere L262-L311 (关键字占位符重建 L296-L300), deleteOrphanJobs L370-L385 (status <> processing)", - "Static read only; no database, test or build execution." - ] - }, - { - "path": "backend/internal/securityaudit/prompt_repository_integration_test.go", - "candidate_owner": "admin-observability", - "role": "test-or-fixture", - "present": true, - "content_sha256": "84f8c2adf43d72d3cd61b6ab9b9aab28167d28bb7c5c45d87e6bd5bea14a6864", - "review_fingerprint": "84f8c2adf43d72d3cd61b6ab9b9aab28167d28bb7c5c45d87e6bd5bea14a6864", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "提示词审计仓储的 Postgres 集成测试 (PROMPT_AUDIT_TEST_POSTGRES_DSN 未设置则 Skip): 执行 181/182 迁移两次验证幂等, 断言表无 raw/credential 类列名、16 个索引存在、CHECK 约束生效; 事件表保留 full_prompt 而 job 行与 redacted_preview 不含明文、失败原因被稳定化不含原始 guard 响应; 并发准入只允许一个 (ErrQueueFull/ErrQueueAdmissionBusy)、claim 版本围栏与 ReclaimStale 使旧租约 ErrLeaseLost; 外键置空后身份快照保留; 高水位删除不影响预览后新建事件、processing job 不被当孤儿删除、重复 ID 去重; PromptService 确认令牌删除与并发 DeleteEventsByFilter 合计恰好删除全部匹配。测试实质与上游 aea725f 相同; 下游唯一改动 (+2 -2) 是驱动从 github.com/lib/pq (sql.Open(\"postgres\")) 切到 github.com/jackc/pgx/v5/stdlib (sql.Open(\"pgx/v5\")), 与生产驱动一致, 不证明新的下游修复, 故为 reference。仅静态阅读, 未连接数据库。", - "evidence": [ - "Full-file static review (L1-L462): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+2 -2): L17 导入 `_ github.com/jackc/pgx/v5/stdlib` 取代 `_ github.com/lib/pq`; L29 sql.Open(\"pgx/v5\", dsn) 取代 sql.Open(\"postgres\", dsn)", - "被测代码: prompt_event_repository.go (ListEvents/GetEvent/DeleteEventsByIDs/PreviewDelete/DeleteEventsByFilter/FilterHash), prompt_repository.go (CreateStagingWithCapacity/ClaimNextJob/ReclaimStale/RefreshLease/Complete/RecordBlocking/MarkStagingFailed, 不在本切片), migrations/181_prompt_audit.sql 与 182_prompt_audit_full_prompt.sql", - "Integration test statically read only; not executed; no database was contacted." - ] - }, - { - "path": "backend/internal/server/api_contract_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "eb30d6405db0133272d6c7d07cd8839dc0eb8e3e9046c1c616a5c3538a91bf2f", - "review_fingerprint": "eb30d6405db0133272d6c7d07cd8839dc0eb8e3e9046c1c616a5c3538a91bf2f", - "review_status": "pending" - }, - { - "path": "backend/internal/server/middleware/audit_log.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a46dc3a1b63813afacf4a55f2b31e3c0b0f238708c0d3bf22cdd26c24aa5a2e6", - "review_fingerprint": "a46dc3a1b63813afacf4a55f2b31e3c0b0f238708c0d3bf22cdd26c24aa5a2e6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "管理面操作审计中间件: 记录变更类请求与白名单敏感 GET, 捕获并按上限脱敏请求体后回填, 提取操作者身份/凭证掩码/路径参数/脱敏查询串, 允许 handler 通过 SetAuditExtra 附加白名单标量, 由 method+路由模板自动推导动作名。下游相对上游 aea725f (+71 -30): auditExtraAllowedKeys 新增 template_id/template_version/old_sha256/new_sha256/byte_length/revision/bundle_* 等 26 个系统提示词与技能注册表相关标量键; auditSensitiveReads 新增 7 条 system-prompts / skill-registry 读取; auditActionOverrides 新增 14 条 system-prompts 变更动作; 新增 auditPromptBodyOmittedRoutes (创建、保存版本、preview/merge、preview/upstream) 并在凭证省略之前判定, 请求体整体以 占位。已核对: 这些路由由核心 routes/admin.go L180-L212 注册并由 handler/admin/system_prompt_handler.go 处理 (plugins/ 下无 system-prompts 引用), 而携带提示词正文的请求只有 Create (Body L63-L67)、SaveVersion (Body L81-L82)、Preview (ServerInstructions/Body L141-L148), PATCH 更新与 PUT runtime 请求结构不含正文, 故省略列表与实际载荷一致。审计本体是宿主通用机制; 系统提示词属 prompt-skills 域的业务, 若日后其路由迁入插件, 这些路由表应随之迁移。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L395): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f: allowlist 扩展 L61-L68; auditSensitiveReads L129-L135; auditActionOverrides L160-L173; +auditPromptBodyOmittedRoutes L191-L199; 中间件分支 L232-L235 (prompt 省略优先于 credential 省略)", - "call chain: NewAuditLogMiddleware 由 server/routes 挂在认证中间件之后; SetAuditExtra 的 handler 调用方在 handler/admin/system_prompt_handler.go 与 prompt-audit handler; RedactAuditBody/AuditRequestBodyCaptureLimit/MaskAuditCredential 定义于 service 层; 行为由同目录 audit_log_test.go 覆盖 (静态阅读)", - "Static read only; no test, build or production execution." - ] - }, - { - "path": "backend/internal/server/middleware/audit_log_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ab7dd47667de806cfa7bb42d015c3fe22b1678f5712a758b939c4b4ead7aee1b", - "review_fingerprint": "ab7dd47667de806cfa7bb42d015c3fe22b1678f5712a758b939c4b4ead7aee1b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "审计中间件测试: 以内存 gin 路由 + auditCaptureRepository + 真实 AuditLogService (Start/Stop) 端到端验证。上游部分: deriveAuditAction 推导表、prompt-audit 变更路由的稳定动作名与整体省略体、SetAuditExtra 只保留白名单标量 (token/raw_prompt/嵌套 map 被丢弃)、passkey 登录动作名、Ollama 会话路由整体省略。下游新增 (+119): TestSystemPromptAuditRoutesHaveStableActionsAndOmitPromptBodies 断言 13 条 system-prompts 路由动作名与 4 条 prompt 省略路由; TestSystemPromptAuditNeverPersistsPromptOrPreviewInput 对 preview/upstream 断言 RequestBody 为 、不含 canary、白名单键 (template_id/new_sha256/bundle_version_id/status/*_manifest_sha256/total_bytes) 保留而 raw_prompt 被丢弃; TestRemoteSkillPromptDetailAuditDoesNotPersistResponseBodies 对 skill-registry 版本详情 GET 断言动作名且整条审计 JSON 不含响应体中的 canary。断言与 audit_log.go 下游 delta 逐条对应, 证明提示词正文不入审计库。静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L309): artifacts/evidence/v027-claude-S45-backend-pkg-server-2-review.json", - "git diff aea725f (+119 -0): +encoding/json 导入 L6; TestSystemPromptAuditRoutesHaveStableActionsAndOmitPromptBodies L150-L177; TestSystemPromptAuditNeverPersistsPromptOrPreviewInput L179-L227; TestRemoteSkillPromptDetailAuditDoesNotPersistResponseBodies L229-L266", - "被测代码: audit_log.go auditActionOverrides L160-L173, auditPromptBodyOmittedRoutes L191-L199, auditSensitiveReads L134, SetAuditExtra/auditExtraAllowedKeys L55-L100, NewAuditLogMiddleware L206-L339", - "Test source statically read only; not executed." - ] - }, - { - "path": "backend/internal/server/middleware/group_model_allowlist.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d578f0c010f2a4e1b22ae44038d3c4e98d815a78ab336756cfc3047170eecd77", - "review_fingerprint": "d578f0c010f2a4e1b22ae44038d3c4e98d815a78ab336756cfc3047170eecd77", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "分组级模型白名单准入中间件(挂在 apiKeyAuth 之后、compositeTarget 之前)。下游相对上游 aea725f 改了三处:GroupModelAllowlist 新增可选 maxNormalizedBytes 参数,读体按 Content-Type 分流——application/json 与 application/*+json 走 httputil.ReadLenientJSONRequestBodyWithPrealloc(与协议 handler 相同的纯 UnexpectedEOF 容错和归一化上限),multipart/二进制仍严格读体并对超限补 413;路由参数提取改为 strings.Trim(c.Param(\"model\"), \"/\"),适配 gateway.go 的 /v1/models/*model 通配路由并保留 openai/gpt-5.4 命名空间;doc 注释改写。准入规则(Allows、候选生成)仍在 service.GroupModelAllowlist,属宿主通用协议机制,不含插件业务;本文件 delta 是对上游行为的正确性修正。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L34-L38 新增 maxNormalizedBytes 可选参数;L119-L150 groupModelAllowlistModelsFromBody 用 mime.ParseMediaType 分流 JSON 族 → ReadLenientJSONRequestBodyWithPrealloc,其余 → ReadRequestBodyWithPrealloc + 手工 MaxBytesError;L148 requestmodel.ResetRequestBody 回填 PrereadBody。", - "L156-L158 strings.Trim(...,\"/\") 处理通配参数前导斜杠(diff vs aea725f 由 TrimSpace 改为 Trim),与 routes/gateway.go L240/L410 的 /models/*model 注册和 modelPathHandler 归一化一致。", - "调用链:routes/gateway.go L47 middleware.GroupModelAllowlist() 生产不传上限(bodyLimit 已由 RequestBodyLimit 在链前执行);Allows 定义于 service/group_model_allowlist.go L95-L125。L23-L24 注释所述“保留 selector 与白名单开关无关地拒绝”在代码中不存在(L41 快速路径直接放行,rg 未找到 reserved/selector 逻辑),见 findings。", - "静态阅读,未执行测试、未构建。" - ] - }, - { - "path": "backend/internal/server/middleware/group_model_allowlist_body_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cc2c39bbf4b8e666a6de0aa7c283b74c794d99f4648ac1d93c592f0572858e69", - "review_fingerprint": "cc2c39bbf4b8e666a6de0aa7c283b74c794d99f4648ac1d93c592f0572858e69", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(上游无此文件),用自定义 groupAllowlistTerminalBody 在数据读完后注入终止错误,逐例证明白名单中间件读体与协议 handler 一致:完整 JSON+io.ErrUnexpectedEOF 放行并以 *httputil.PrereadBody 回填、被拒模型 EOF 恢复后仍 404、application/vnd.client+json 控制字符归一化为 \\u000a、截断 JSON 与 errors.Join 非纯 EOF 不恢复(400)、gzip 完整体/缺 footer 恢复、multipart 与 octet-stream 保持严格 400、归一化扩张与解压扩张超 limit 返回 413;handler 内还断言 ContentLength 与 Content-Encoding 元数据被重写。证明的是 group_model_allowlist.go 的下游正确性修复,主体为宿主核心;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L17-L36 groupAllowlistTerminalBody;L38-L64 十一组表驱动用例(wantStatus 200/404/400/413);L75 router.Use(GroupModelAllowlist(limit)),limit 默认 1024。", - "L77-L90 handler 断言 c.Request.Body 为 *httputil.PrereadBody、重读字节等于 wantBody、ContentLength==len(got) 且 Content-Encoding 已清除;L119-L121 断言 handler 仅在 200 时被调用。", - "对应实现 group_model_allowlist.go L119-L150;被证明的行为依赖 httputil.ReadLenientJSONRequestBodyWithPrealloc(上游已有,body.go L187)。静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/middleware/group_model_allowlist_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "04decdbb0477b84f5adb70f1bc9149578cef0465c6a1decd05fa17e0957c6db3", - "review_fingerprint": "04decdbb0477b84f5adb70f1bc9149578cef0465c6a1decd05fa17e0957c6db3", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "上游既有的白名单中间件测试集(禁用时不读体、413 透传、OpenAI/Anthropic/Google 三种错误格式、Gemini 路由参数与 models/ 前缀、Realtime 查询参数、multipart 首末值、重复键与大小写键、Live 以 session.model 为准、伪造 Upgrade 头不绕过、nil Group 放行)。下游 delta 仅两处:newGroupModelAllowlistTestRouter 在非 /v1beta 前缀改注册 GET /models/*model 通配(与生产 gateway.go 一致,参数带前导斜杠);新增 TestGroupModelAllowlistCatchAllModelRouteParamKeepsNamespace 证明 GET /v1/models/openai/gpt-5.4 去掉前导斜杠后命中白名单条目 openai/gpt-5.4。其余断言为上游内容;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L39-L45 按前缀分别注册 /models/:model(v1beta)与 /models/*model(其他);L239-L248 新增 catch-all 命名空间用例,期望 200。", - "diff vs aea725f 仅 +13 行(路由注册分支 + 新用例),证明 group_model_allowlist.go L157 strings.Trim(...,\"/\") 的修复;其余 25 个测试函数与上游相同。", - "测试主体为宿主中间件(core),未涉及插件;静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/middleware/openai_fast_policy_forwarding_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "163eba7622f50d4dfc3ecdb8c06071723e60d06828919a3104578bf66235aac3", - "review_fingerprint": "163eba7622f50d4dfc3ecdb8c06071723e60d06828919a3104578bf66235aac3", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "上游测试:以 NewAPIKeyAuthMiddleware + OpenAIGatewayService.Forward 打到本地 httptest 上游,证明按用户 ID 作用域的 OpenAI fast policy(priority 档对 user 42 pass、对 user 43 filter)会体现在上游请求体 service_tier 字段。下游 delta 仅为 openAIFastPolicyForwardingSettingRepo 补一个返回空 map 的 GetMultiple 桩:下游 OpenAI 转发路径经 openai_refusal_recovery.go L260 → SettingService.GetOpenAIRefusalRecoveryRuntime(setting_gateway_runtime.go L213-L240,上游无此函数)调用 settingRepo.GetMultiple,嵌入的 nil SettingRepository 接口会 panic,故需桩方法。不证明任何下游修复,按 reference 记录;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L21-L132 主测试:两把 key(user 42/43)同组 101,L130-L131 断言 allowedUserBody.service_tier==priority 且 otherUserBody 无 service_tier。", - "diff vs aea725f 仅 L179-L181 新增 GetMultiple 桩;对应下游 service/setting_gateway_runtime.go L233 GetOpenAIRefusalRecoveryRuntime 内的 GetMultiple(由 openai_refusal_recovery.go L260 在转发路径调用;上游 setting_gateway_runtime.go 无该函数)。", - "测试主体为宿主 OpenAI 网关与设置服务(core-quota-and-protocol);静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/router.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "23ad732e342dc890ce54898978a3f96f48245519239bac64d883d3fcdf47819c", - "review_fingerprint": "23ad732e342dc890ce54898978a3f96f48245519239bac64d883d3fcdf47819c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主路由器装配:全局中间件、CSP frame-src 缓存刷新、内嵌前端、各模块路由注册。下游 delta 两处:内嵌前端不再以 r.Use 全局中间件挂载,而是构造 handler 后交给 web.RegisterFrontendFallback 作为 NoRoute 兜底(注释:前端绝不做 API 前置拦截器);在 h.RemoteSkill 非空时注册公开 /skills/security-research/current 与 /*path → RemoteSkillHandler.Serve(仅 GET/HEAD,拒绝 %2e/%2f/%5c 编码穿越,读 RemoteSkillRegistryService 已发布文件)。前者是宿主通用机制修正;后者把 prompt-skills 域的固定业务路径硬编码进宿主路由,属宿主到插件的挂载胶水,本文件本身不含业务规则。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L73-L91 frontend 变量由 web.ServeEmbeddedFrontend()/frontendServer.Middleware() 赋值,L95 web.RegisterFrontendFallback(r, frontend)(diff 删除两处 r.Use);对应 web/frontend_routes.go 与 web/agent_route_ownership_test.go。", - "L118-L121 h.RemoteSkill 路由(diff 新增);handler 定义 handler/remote_skill_handler.go L30-L55,读 service.RemoteSkillRegistryService。", - "L134-L141 各模块注册顺序与上游一致;静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/account_job_routes_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a3bc63285d40f55abd2b7c925cb798073d369bb34c0b91d085fb0d8ccbfe63dc", - "review_fingerprint": "a3bc63285d40f55abd2b7c925cb798073d369bb34c0b91d085fb0d8ccbfe63dc", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "下游新增路由契约测试:用全 nil 依赖构造 AccountHandler/AccountJobHandler,以直接放行的 adminAuth/auditLog/stepUp 桩和 nil settingService/panelRateLimiter 调用 RegisterAdminRoutes,断言 /api/v1/admin/account-jobs 的列表/详情/items/cancel/retry-failed 与账号工具资源路由 accounts/data/preview、batch-test、batch-test-models、duplicates/review、duplicates/merge 均已注册。只证明路由表存在,不触发 handler,也不校验 RegisterResource 的插件资源作用域;主体是宿主作业 API 与 account-tools 资源在 admin.go/plugin_account_tools.go 的挂载点。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L17-L24 构造 handlers 并调用 RegisterAdminRoutes(..., nil, nil);L30-L44 十条期望的 method+path 全部 require.True。", - "依赖 nil 安全:h.Admin.Plugin 为 nil 时 RegisterResource(plugin_resources.go L22-L27)与 AccountViewRequest 需处理 nil 接收者,panelRateLimiter.Global()/AdminComplianceGuard(nil) 同理;batch-test/batch-test-models 由 routes/plugin_account_tools.go L26-L27 注册。", - "静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/admin.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f71ad9c23135a5637f2f68b4fe91afbe7b34b951daa4c772d06cf9724baa8df2", - "review_fingerprint": "f71ad9c23135a5637f2f68b4fe91afbe7b34b951daa4c772d06cf9724baa8df2", - "review_status": "pending" - }, - { - "path": "backend/internal/server/routes/auth.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "fbcfbbc691470b75807a58da9aaa560c7e3daf0aa188628ee0b20ff8c18ecc40", - "review_fingerprint": "fbcfbbc691470b75807a58da9aaa560c7e3daf0aa188628ee0b20ff8c18ecc40", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "认证/公开设置/当前用户路由。下游 delta 仅在公开 /settings 组新增两条:GET /settings/plugins → SettingHandler.GetPublicPluginContributions(Cache-Control no-store,返回 pluginManager.PublicContributions());GET /settings/plugins/:id/theme/:revision/*path → GetPublicPluginThemeAsset(css/woff2、nosniff、same-origin CORP,经 pluginManager.ReadPublicThemeAsset 按插件 id/revision 读取)。二者是宿主对插件 UI 贡献的公开只读桥接,不含插件业务;其余 OAuth/限流/BackendMode 守卫与上游一致。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L243-L250 settings 组(PublicIP 限流)新增 L247-L248 两条路由(diff 仅 +2 行);handler 在 handler/setting_handler.go L25-L53。", - "L28-L239 auth 公开接口与 L252-L263 认证接口与上游相同;静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/composite_platform_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0307edd5d4e318a420f04337ee11769482e080330982cea2b71ec0f823347671", - "review_fingerprint": "0307edd5d4e318a420f04337ee11769482e080330982cea2b71ec0f823347671", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "合成分组目标平台中间件测试。下游新增 compositeTerminalErrorReader 及四组用例:完整 JSON+UnexpectedEOF 恢复为 204、application/vnd.openai+json gzip 体+EOF 恢复并清除 Content-Encoding、截断 JSON 与 multipart EOF 仍 400、readCompositeRequestBody 对 JSON 归一化扩张与二进制严格上限返回带 Limit 的 *http.MaxBytesError;并把 TestCompositeRequestModelFromMultipartLiveSession 重命名为 TestRequestModelFromMultipartLiveSession。证明 gateway.go readCompositeRequestBody 的下游修复(合成中间件与协议 handler 的读体容错一致);显式路由改写、Live 按 session.model 分发、Gemini 路径路由等用例为上游内容。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L21-L36 compositeTerminalErrorReader;L104-L191 三组 EOF 用例均以 compositeTargetPlatformMiddleware(nil, 1024) 构链;L305-L325 限额用例断言 maxErr.Limit==tc.limit。", - "diff vs aea725f:+gzip 导入、+reader、+4 个测试函数、1 处重命名;对应实现 gateway.go L577-L662。", - "测试主体为宿主合成路由机制(core-quota-and-protocol);静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/gateway.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "39dd118c8d148fdec4b12ac7358360d3d152c51e226e4c96ee73c9be14775935", - "review_fingerprint": "39dd118c8d148fdec4b12ac7358360d3d152c51e226e4c96ee73c9be14775935", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "网关路由注册(/v1、/v1beta、根路径别名、/backend-api/codex、antigravity)。下游 delta:countTokensHandler 把 PlatformCindy 并入走 OpenAIGateway.CountTokens 的分支;modelsHandler 仅在集合请求(c.Param(\"model\")==\"\")且带 client_version 时选 Codex 清单;单模型发现改为 GET /models/*model 通配 + modelPathHandler(去前导斜杠、就地改写 c.Params、空→列表、capabilities→ModelCapabilities,仅 /v1 前缀开放 capabilities),以支持 openai/gpt-5.4 命名空间;compositeTargetPlatformMiddleware 新增可选归一化上限并经 readCompositeRequestBody 对 JSON 族使用宽容读体、multipart/二进制保持严格。以上为宿主协议路由机制与其正确性修正;Cindy 一行是平台→协议 handler 的分发,不含 cindy-provider 业务规则。生产调用 GroupModelAllowlist()/compositeTargetPlatformMiddleware(resolver) 均不传归一化上限(依赖链前 RequestBodyLimit)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L60-L69 countTokensHandler 含 PlatformCindy(diff 新增);L73-L106 modelsHandler/modelPathHandler;L240 与 L410 注册 /models/*model(diff 由 /models/:model 改为通配)。", - "L577-L662 compositeTargetPlatformMiddleware(resolver, maxBodySize...) + readCompositeRequestBody + compositeJSONContentType(diff 新增);L38、L47 生产装配不传上限。", - "L214-L223 与 L395-L397、L413 三条链均为 apiKeyAuth→groupModelAllowlist→compositeTarget→requireGroup,白名单在合成改写前;静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/gateway_codex_models_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fd42fb21a6da939d5546fb428a9f4141bd76fb65c698469391f62f37a02ed677", - "review_fingerprint": "fd42fb21a6da939d5546fb428a9f4141bd76fb65c698469391f62f37a02ed677", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "上游测试:断言 /backend-api/codex/models、/v1/models、/models 已注册且根别名与 /v1/models 使用同一 handler,并证明 dispatchCodexModelsGateway 只对 PlatformOpenAI 走 OpenAI 清单 handler(composite/grok/deepseek 走生成 handler)。下游 delta 仅新增一条断言:GET /v1/models/*model 已注册(服务 capabilities 与带命名空间的单模型查询),证明 gateway.go 由 /models/:model 改为通配路由的修复。主体为宿主网关路由;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L14-L29 路由注册断言,L26 为 diff 新增(/v1/models/*model);L31-L65 dispatchCodexModelsGateway 平台分发表驱动测试。", - "依赖 gateway_test.go 的 newGatewayRoutesTestRouter;对应实现 gateway.go L240。静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/gateway_group_fixture_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f3611cadaec82bc00f3e256b9693f54d048b79d5c1707b244e2e7f8759ecf1b7", - "review_fingerprint": "f3611cadaec82bc00f3e256b9693f54d048b79d5c1707b244e2e7f8759ecf1b7", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试夹具(非测试函数):gatewayRoutesGroupRepository 嵌入 service.GroupRepository,仅实现 GetByIDLite/GetByID 按 ID 返回固定分组副本;newGatewayRoutesHandlerForGroup 用它构造 service.NewGatewayService 与 handler.NewGatewayHandler(其余依赖为 nil),让网关路由测试在注入已鉴权 key 的同时仍经真实的当前分组只读来源,使白名单/平台门禁断言跑完整中间件链。不含断言、不证明修复,属测试支撑材料;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L15-L30 仓储桩(ID 不匹配返回 service.ErrGroupNotFound,返回值为拷贝);L32-L36 handler 构造函数。", - "被 gateway_model_allowlist_test.go / gateway_models_pinned_test.go 等同包测试使用;静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/gateway_model_allowlist_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fe0654be53d4e0e1fd7e8b259fce297b696f1212cde1fd378a730ef577db02a8", - "review_fingerprint": "fe0654be53d4e0e1fd7e8b259fce297b696f1212cde1fd378a730ef577db02a8", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "网关路由层白名单测试(上游既有):源码级正则断言每条网关链在 apiKeyAuth 之后、compositeTarget 之前挂 groupModelAllowlist,且带 apiKeyAuth 的根路径路由必须收敛到 rootRoute;合成分组的公开模型在改写前被 404;27 条根别名//v1//codex//antigravity 路径逐一被拒;WS 升级放行;无模型路由不受影响。下游 delta 仅为夹具改造:newGatewayRoutesTestRouterWithGroup 给分组默认 ID=1、Status=active,用 newGatewayRoutesHandlerForGroup(cfg, group) 构造带真实分组只读来源的 GatewayHandler 替代空结构体,并以 &group.ID 作 GroupID——适配下游 GatewayHandler 经 GatewayService 读取当前分组的托管守卫。断言本身与上游一致,不证明下游修复;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L19-L51 夹具(diff 仅此处:+ID/Status 默认值、+cfg 变量、Gateway 由 &handler.GatewayHandler{} 改为 newGatewayRoutesHandlerForGroup,GroupID 指向 group.ID)。", - "L67-L105 读取 gateway.go 源码做正则断言(rootRoute 顺序、四条 Use 链、codexDirect 单行链、无游离 r.METHOD(...apiKeyAuth));L134-L182 27 条路径均期望 404 且含 'not available for this group'。", - "夹具依赖 gateway_group_fixture_test.go;静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/gateway_models_pinned_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "23ac438e31d96b4c6be6dfb57605ecb6c08ee5eba1c1627ab43332107292670f", - "review_fingerprint": "23ac438e31d96b4c6be6dfb57605ecb6c08ee5eba1c1627ab43332107292670f", - "review_status": "pending" - }, - { - "path": "backend/internal/server/routes/gateway_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0cd615d44effb2a79fac1c3fb7d746225ab0d4c39be306c90841618ac5648767", - "review_fingerprint": "0cd615d44effb2a79fac1c3fb7d746225ab0d4c39be306c90841618ac5648767", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "网关路由注册与平台门禁测试集(上游既有):responses/compact、alpha/search、images、async images、Grok 媒体与自定义音色 CRUD、grokCustomVoiceEndpoint 按路由模板而非原始路径、composite 视频查询走 Grok、非 Grok 视频 404、composite embeddings 需 OpenAI 目标、Grok CLI 兼容入口与 count_tokens、responses 子路径穿越/编码在入口 404。下游 delta 仅为共享夹具:newGatewayRoutesTestRouterWithConfig 构造 {ID:1, Platform, Status:active} 的分组并用 newGatewayRoutesHandlerForGroup(cfg, group) 替代空 GatewayHandler,GroupID 指向 group.ID,使 handler 内的当前分组读取有真实来源。断言与上游一致,不证明下游修复;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L27-L59 夹具(diff 仅 +group 变量、Gateway 构造方式、GroupID/Group 指向同一对象)。", - "L61-L468 共 15 个测试函数与上游相同,其中 L435-L457 锁定 /responses/*subpath 对 ..、%2e%2e、反斜杠、%3f、%23 等子路径在入口 404 且报 'Unsupported responses subpath'。", - "静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/plugin_account_tools.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "66fa09f9e56aa39f6ff0e7796d9e836017cc08e858052a7bc766c1d3dc232361", - "review_fingerprint": "66fa09f9e56aa39f6ff0e7796d9e836017cc08e858052a7bc766c1d3dc232361", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "Full-file review and fix: only the two destructive global classification resources require AllAccounts; existing per-account and filtered target descriptors are preserved.", - "evidence": [ - "Read all 40 final lines. Every named operation is CapabilityAdmin/permission admin and goes through RegisterResource before the original authenticated handler.", - "Before the fix, taxonomy.folders.delete/taxonomy.tags.delete had no account selection fields or AllAccounts flag. resourceAccountTargets returned no IDs/non-filtered, so RegisterResource skipped account scope/rollout validation despite these handlers affecting all associated accounts.", - "Both delete descriptors now set AllAccounts=true via accountToolResourceRequiresAllAccounts. Existing middleware and ResourceDescriptors use the same wildcard platform/type, 100% binding check; no partial-account deletion/filtering was introduced.", - "taxonomy.account.update still declares AccountParam=id; taxonomy.bulk.update still declares account_ids and filters. Batch-test descriptors and non-delete taxonomy metadata operations are unchanged." - ] - }, - { - "path": "backend/internal/server/routes/plugin_account_tools_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d4d25f80cfd88c7b8a03a78a1ced297846199b0a62dd6c90dca19bf9f3d11dbd", - "review_fingerprint": "d4d25f80cfd88c7b8a03a78a1ced297846199b0a62dd6c90dca19bf9f3d11dbd", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "New narrow route-contract test verifies that global deletion is marked full-account without widening permissions for other resources.", - "evidence": [ - "Both taxonomy.folders.delete and taxonomy.tags.delete must require full account scope.", - "Folders/tags list/create/order/update, individual assignment, bulk classification and batch-test resources must not be converted into full-account-only operations by this change.", - "The test checks the registration helper contract. Live HTTP server execution and real account deletion were not run; the matching manager scope gate is exercised separately." - ] - }, - { - "path": "backend/internal/server/routes/system_prompt_routes_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0aba7db4b32443eecc60ad2c642416bad09b6738d52616644b6b1c8bfb748dbe", - "review_fingerprint": "0aba7db4b32443eecc60ad2c642416bad09b6738d52616644b6b1c8bfb748dbe", - "review_status": "reviewed", - "decision": "adapter", - "owner": "prompt-skills", - "reason": "下游新增路由鉴权顺序测试:以只含 SystemPrompt handler(nil 依赖)的 Handlers 和一个对无 Authorization 返回 401、有则返回 403 的 adminAuth 桩调用 RegisterAdminRoutes,请求 GET /api/v1/admin/system-prompts/skill-registry/versions/12,断言未认证 401、非管理员 403。它只证明 prompt-skills 域的 skill-registry 版本详情路由挂在 admin 组且 adminAuth 先于 handler 执行(路由不存在则会是 404),不触及 handler 与 RegisterResource 的插件资源绑定逻辑。属宿主对 prompt-skills 管理路由挂载的桥接测试;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L18-L30 构造 handlers 与 401/403 的 adminAuth 桩并调用 RegisterAdminRoutes(..., nil, nil);L32-L50 两组用例分别期望 401 与 403。", - "对应 admin.go L180-L212 registerSystemPromptRoutes 中 skills.version 路由(prompts.Handle + h.Admin.Plugin.RegisterResource);与 account_job_routes_test.go 相同依赖 nil 接收者安全。", - "静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/server/routes/user.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5a6351ea8c236f2b55a2519948eb5d2d1bac3fa7a146c4127bca44da3d2fd7f0", - "review_fingerprint": "5a6351ea8c236f2b55a2519948eb5d2d1bac3fa7a146c4127bca44da3d2fd7f0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "已认证用户路由(jwtAuth→BackendModeUserGuard→panelRateLimiter.Global→auditLog)。下游 delta:新增用户侧插件资源发现与 UI 会话路由 GET /plugins/:id/resources、POST /plugins/:id/ui-session(h.Admin.Plugin.UserResources/CreateUserUISession);新增 /image-studio 组八条路由,全部经 h.Admin.Plugin.RegisterResource 以 Permission=\"user\"、Capability=request 的 ResourceDescriptor 注册(列表/详情/items/cancel/artifact 为 Retained,artifact ResponseKind=blob),另登记四个 Method=\"LOCAL\" 的 image.history.* 保留资源(无 HTTP 路由)。这些是宿主为 image-tools 插件与通用插件用户界面提供的挂载胶水,不含生图业务规则;其余 user/keys/groups/channels/usage/announcements/redeem/subscriptions/channel-monitor 路由与上游一致。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L29-L30 用户侧插件资源/UI 会话路由(diff 新增);L101-L118 image-studio 表驱动资源路由;L119-L121 LOCAL 资源登记(返回的 handler 被丢弃,仅副作用登记)。", - "RegisterResource 对重名 panic(handler/admin/plugin_resources.go L31-L33),本文件 12 个资源名唯一;handler 由 h.ImageStudio 提供,业务不在本文件。", - "静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/service/account.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "28c505ae76608b8738f440eb2f610d36cd468a2fadd89d4ae6b28925c12728a3", - "review_fingerprint": "28c505ae76608b8738f440eb2f610d36cd468a2fadd89d4ae6b28925c12728a3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Account 领域模型:调度可用性判定(IsSchedulable/限流/过载/临时停调/配额超限/窗口费用/RPM 三态)、model_mapping 缓存与通配符解析、OpenAI/CN/Grok 平台辨识与 base_url、端点能力判定。下游相对上游 aea725f 新增 WirePlatform/ProviderProfile/ManagementFolderID、Cindy 终态字段(BalanceInsufficientAt/BannedAt/CredentialGeneration 与展示用 probe 字段)、ManagementFolder/Tags 展示元数据、ModelContextOverridesPatch 写意图;IsSchedulable 增加 hasCindyTerminalSchedulingBlock 与 QuotaState(now).Blocked 两道门;IsModelSupported/ResolveMappedModel 前置三级 Cindy 身份分支(legacy→runtime-compatible→exact,目录查询经 cindy_capability_catalog.go 的 queryCindyCatalog 转发给插件);IsOpenAI/IsOpenAICompatible 改用 EffectiveWirePlatform;新增 Messages/CountTokens 能力回落 chat_completions;新增 OpenAI reasoning 策略读取(经 plugin_codex_recovery.go 调 codex.recovery.enabled)。归为宿主通用机制(调度/配额),Cindy 分支只是身份判定+插件目录查询的适配,未发现第二套目录实现;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (154 lines): struct fields L29-L30/L37/L53-L63/L80-L88, AccountManagementFolder/Tag L108-L126, IsSchedulable Cindy gate L233-L235 and QuotaState gate L246-L248, hasCindyTerminalSchedulingBlock L342-L345, IsModelSupported Cindy branches L915-L934, ResolveMappedModel Cindy branches L969-L986, IsOpenAI via EffectiveWirePlatform L1392-L1394, capability Messages/CountTokens L1941/L1956-L1966, reasoning policy getters L2200-L2228.", - "Call chain: IsCindyAPIKeyAccount/IsLegacyCindyAPIKeyAccount defined in service/cindy_identity.go L33-L51 (base_url host api.laxarouter.ai); CindyCompatibilityMappedUpstreamModel/CindyMappedUpstreamModel/CindyModelHasVerifiedEndpoint in service/cindy_capability_catalog.go L121-L184 are thin wrappers over queryCindyCatalog (plugin registry plugins/cindy-provider/catalog/catalog.go L238-L391); EffectiveWirePlatform/hasCanonicalCindyProviderIdentity in service/provider_identity.go L44/L107; QuotaState in service/account_quota_windows.go L164; openAIReasoningPolicyEnabled in service/plugin_codex_recovery.go L88-L100 invokes extension capability recovery with 1s timeout.", - "Scheduling state is per-account struct data; scheduler code is told not to consult ManagementFolder/Tags (comment L108-L109). No secrets logged in this file (GetWebSearchEmulationMode logs only account_id and a bool).", - "Low-severity observation recorded in findings: provider-specific Cindy branch ordering lives in the core Account methods; not claimed to be a duplicated executor. No production behavior edit or test execution." - ] - }, - { - "path": "backend/internal/service/account_available_models_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "13799843e627c013b48b18dc4bfb50871c0b8e0fa81da4fdab5cd43c7ff9049e", - "review_fingerprint": "13799843e627c013b48b18dc4bfb50871c0b8e0fa81da4fdab5cd43c7ff9049e", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "下游新增测试(上游无此文件),对象是宿主 AccountTestService.FetchOpenAIAccountModels(account_test_service.go L193,供 admin account_handler.go L2848 的可用模型选择器使用)。三个测试断言:APIKey 账号的展示投影复用 gateway.FetchOpenAIModelsList 的发现缓存且只打一次上游 /v1/models、不改写缓存 Body/ETag、不改写 account.Credentials(含 model_mapping),调用方修改返回值不影响再次投影;OAuth 发现结果保持原始表示并追加内建 gpt-image 标签与精确 ID;空目录返回空切片而 missing/null/error/空 ID 目录在展示转换前即报错。属于宿主账号管理功能的静态阅读测试,不证明相对上游的缺陷修复;未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "New downstream file (git ls-tree aea725f prints nothing). Tests L16-L62 (cache/credentials immutability, calls==1), L64-L99 (OAuth projection + built-in image labels, ETag unchanged), L101-L135 (empty vs invalid catalog table).", - "Subject traced: FetchOpenAIAccountModels defined in service/account_test_service.go L193; sole production caller handler/admin/account_handler.go L2848. Fixture testdata/account_available_models_contract.json referenced at L17 (not opened).", - "Statically read only; no test execution, no behavior claim beyond what the assertions state." - ] - }, - { - "path": "backend/internal/service/account_base_url.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a913d96374c4013294693eb4fb9b4c6b7917af7075482c7e93331cc246328617", - "review_fingerprint": "a913d96374c4013294693eb4fb9b4c6b7917af7075482c7e93331cc246328617", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "下游新增的通用输入归一化:NormalizeUpstreamBaseURLInput 给管理端粘贴的 host/path 简写补 https://,保留显式 scheme 与 //协议相对写法;NormalizeAccountCredentialBaseURLs 对 credentials.base_url 与 api_base_urls(map[string]any / map[string]string 两种形态)幂等归一化。被 AccountService.Create/Update、admin_account.go 创建/更新/导入、account_test_service.go 与 admin account_handler 调用,是宿主账号 CRUD 的通用机制,不含任何供应商业务规则。注释声明 URL 校验仍在请求边界进行,本次未核验该边界;静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "New downstream file. NormalizeUpstreamBaseURLInput L13-L25 (trim, // prefix, scheme check via url.Parse + '://' guard), NormalizeAccountCredentialBaseURLs L31-L50.", - "Callers (rg): service/account_service.go L226/L336, service/admin_account.go L561/L575/L705/L777, service/account_test_service.go L277, handler/admin/account_handler.go L2996/L3003.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/account_base_url_input_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "439e4c21826a21f77956454f9d7667ce01419de54c852a0484b196adaaceebf6", - "review_fingerprint": "439e4c21826a21f77956454f9d7667ce01419de54c852a0484b196adaaceebf6", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "下游新增测试,覆盖 account_base_url.go:表驱动断言 host 简写补 https、https/http 显式 scheme 原样保留、//协议相对补 https:、空白输入得空串;第二个测试断言 NormalizeAccountCredentialBaseURLs 同时归一化 base_url 与嵌套 api_base_urls 的 chat_completions 项而保留已带 scheme 的 anthropic 项。测试的是宿主通用输入归一化,非插件业务;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "New downstream file. TestNormalizeUpstreamBaseURLInput L5-L24 (5 cases), TestNormalizeAccountCredentialBaseURLs L26-L48.", - "Subject: service/account_base_url.go (same slice).", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/account_business_errors.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2f036f1a0a9c5337f0c3f0a06f501f5e0dbd98d342d6ffb4dd89b27e13d4054b", - "review_fingerprint": "2f036f1a0a9c5337f0c3f0a06f501f5e0dbd98d342d6ffb4dd89b27e13d4054b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "下游新增的账号任务/导入结果码到固定、不含凭据的业务消息的目录。导入类结果码常量直接取自 SDK pkg/extensionapi/v1(AccountImportCode*),任务类码为宿主常量;AccountBusinessMessage 对 ticket_ 前缀委托给 CodexTicketFailure(宿主侧 codex_ticket_lifecycle.go 的票据失败消息表),NormalizeAccountBusinessFailure 只放行标记 failure 的条目、把预览类 create/update 与未知码一律折叠为 execution_failed,避免把原始错误泄露给调用方。属于宿主任务运行时的结果渲染机制;但目录里混有 Cindy 清理/导入、taxonomy、ticket 等插件域文案(见 findings 低危观察)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "New downstream file. Code constants L8-L29 (import codes aliased from extensionv1), catalog L36-L81, AccountBusinessMessage L85-L94 (ticket_ prefix -> CodexTicketFailure), NormalizeAccountBusinessFailure L98-L109 (failure-only admission, fallback execution_failed).", - "Call chain: CodexTicketFailure defined in service/codex_ticket_lifecycle.go L82 (host-side message table; ticket execution itself is invoked through pluginManager in service/codex_ticket_plugin.go L70-L91). No ticket message table found in plugins/codex-runtime via rg, so no duplicated executor.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/account_business_errors_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9d8bcbcc82b3eb10d7cc5da4a3ad9595f05980c381804611e322008e5349d00e", - "review_fingerprint": "9d8bcbcc82b3eb10d7cc5da4a3ad9595f05980c381804611e322008e5349d00e", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "下游新增测试,单个用例断言:AccountBusinessMessage 能解析预览码 create 的文案;NormalizeAccountBusinessFailure 对 Cindy 导入目标缺失码与 delete_failed 原码返回;对预览码 create/update、未知码与空串一律折叠为 execution_failed 与其固定文案。证明的是宿主结果码目录的安全折叠行为,非插件业务规则;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "New downstream file. Single test L9-L28 with require assertions on both exported functions.", - "Subject: service/account_business_errors.go (same slice).", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/account_credential_identity.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c3c0a9af6e21f2fb166f4864d3b8cbb9c1a36313cfc49978f910f518a7583198", - "review_fingerprint": "c3c0a9af6e21f2fb166f4864d3b8cbb9c1a36313cfc49978f910f518a7583198", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "下游新增的账号凭据身份(非密钥的持久化指纹)领域类型、绑定参数/结果、仓储接口(含事务版)以及校验与指纹算法:指纹为带域前缀与长度前缀的 SHA-256,API key 原始字节参与摘要但不存储;base_url 只接受 https://api.laxarouter.ai 精确根(拒绝 http、路径、query、userinfo、显式端口),ProviderProfile 只接受 ProviderProfileCindyLaxaV1。数据层机制归核心,但校验被硬编码为唯一的 Cindy 供应商档案,属于核心中承载单一供应商规则(见 findings 中危观察,rg 未在 plugins/cindy-provider 发现同一规则,故非重复执行器)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "New downstream file. Types/repository interfaces L26-L67, ValidateAccountCredentialIdentityBinding L69-L83 (profile must equal ProviderProfileCindyLaxaV1, fingerprint 64 lowercase hex), NormalizeCredentialIdentityBaseURL L88-L104 (exact HTTPS root of cindyAPIHost), AccountCredentialFingerprint L108-L127 (domain sub2api/account-credential-identity/v1, length-prefixed parts).", - "cindyAPIHost constant comes from service/cindy_identity.go L23; rg in plugins/cindy-provider for fingerprint/laxarouter shows only catalog/management.go member-fingerprint hex checks and a metadata revision string, no duplicate identity rule.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/account_credential_identity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0176c9884564d7c63ac237d243646306e316443269214d0456a2be36584fd6e3", - "review_fingerprint": "0176c9884564d7c63ac237d243646306e316443269214d0456a2be36584fd6e3", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "下游新增测试:断言 NormalizeCredentialIdentityBaseURL 对大小写混写的 https://API.LAXAROUTER.ai/ 归一为精确根,并对 http、/v1 路径、query、userinfo、:443 显式端口、其他 host 六种输入返回 ErrCredentialIdentityInvalid;断言指纹确定性、长度 64 hex、原始 key 字节(含空格)参与摘要(去空格后指纹不同),以及大写指纹在 ValidateAccountCredentialIdentityBinding 中被拒。证明的是核心凭据身份机制的边界,未涉及插件;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "New downstream file. TestNormalizeCredentialIdentityBaseURLIsExact L11-L23, TestAccountCredentialFingerprintPreservesRawKeyBytesAndSeparatesDomain L25-L44.", - "Subject: service/account_credential_identity.go (same slice).", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/account_edit_bulk.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "53fa90c9fe2d8ac11839c75167e103c32a90fe0a618ec09534cf9e581a45d78b", - "review_fingerprint": "53fa90c9fe2d8ac11839c75167e103c32a90fe0a618ec09534cf9e581a45d78b", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_edit_codec.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "35e4203c977ce1f0430b4f8f34cee271f2a35a77e43605973157d214c4a69ca4", - "review_fingerprint": "35e4203c977ce1f0430b4f8f34cee271f2a35a77e43605973157d214c4a69ca4", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_job.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "a4489fa0d0dc5ab29177e5e21a79b14140c5d1a82ca0620ba4c71b1b0d47be3b", - "review_fingerprint": "a4489fa0d0dc5ab29177e5e21a79b14140c5d1a82ca0620ba4c71b1b0d47be3b", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_job_batch_test_runtime.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "1b724ccbad66a23b0157958cf5fb391784e2fc291a2ca48720aea7a13f3d3647", - "review_fingerprint": "1b724ccbad66a23b0157958cf5fb391784e2fc291a2ca48720aea7a13f3d3647", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_job_plugin.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c5d7debc8f73e25a6028503407ed953e984cc42822afa45604037cc116e8b9e3", - "review_fingerprint": "c5d7debc8f73e25a6028503407ed953e984cc42822afa45604037cc116e8b9e3", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_job_plugin_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3752f58dd7cd4caa87b381fb41ea96a03d0c4d81cf165a30b707b7a0e9d936ac", - "review_fingerprint": "3752f58dd7cd4caa87b381fb41ea96a03d0c4d81cf165a30b707b7a0e9d936ac", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Full unit-tagged fixture and five test functions read. Assertions cover generation rejection, lease held until actual cleanup after drain, retry owner/current generation and narrowed import scope, actual admin target/type/cohort, old ownerless import lifetime without history rewrite, and cancellation exactly once versus successful completion. The process boundary and repository are synthetic; the fixture's release-only lease does not claim real PostgreSQL session-loss detection.", - "evidence": [ - "No cases rerun because this file was unchanged. Compile/run coverage is recorded in prior source-bound host job evidence; this record reviews assertions rather than substituting test names for review.", - "artifacts/evidence/v027-host-job-wiring-static-review.json" - ] - }, - { - "path": "backend/internal/service/account_job_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "61ad1495f2d8fc96a0c92fef042881b7950de6320142fef8c37147e1b91f6531", - "review_fingerprint": "61ad1495f2d8fc96a0c92fef042881b7950de6320142fef8c37147e1b91f6531", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_quota_schedulable_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3b5a49f6ca40ae4d8a73389a07c28e9e3c35efa272761a7caf094d349a1c978c", - "review_fingerprint": "3b5a49f6ca40ae4d8a73389a07c28e9e3c35efa272761a7caf094d349a1c978c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static test source covers ordinary API key and Bedrock total/daily/weekly quota gating and confirms OAuth ignores API-key quota fields; test execution was not repeated.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=3b5a49f6ca40ae4d8a73389a07c28e9e3c35efa272761a7caf094d349a1c978c; current_sha256=3b5a49f6ca40ae4d8a73389a07c28e9e3c35efa272761a7caf094d349a1c978c; inventory_sha256_match=true", - "lines 43-136: daily, weekly, total, expired-period, OAuth, and Bedrock cases", - "caller under test: backend/internal/service/account.go:229-255" - ] - }, - { - "path": "backend/internal/service/account_quota_window_state.go", - "candidate_owner": "core-quota-and-protocol", - "role": "source", - "present": true, - "content_sha256": "047cc4c6642a225a2bd1589a946fe3be96a60b9b59e45564a5fec20fcdc9ddf7", - "review_fingerprint": "047cc4c6642a225a2bd1589a946fe3be96a60b9b59e45564a5fec20fcdc9ddf7", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_quota_window_state_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "51c71acf7dc423bbbb38d6d5d1d52d7fbc6e88105b3b207b00c5053c21f8a1ec", - "review_fingerprint": "51c71acf7dc423bbbb38d6d5d1d52d7fbc6e88105b3b207b00c5053c21f8a1ec", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_reasoning_policy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "802acf025b55dcfa6c69ffe12629dd45300fc28cbb531d2a7e858cf4be17ce65", - "review_fingerprint": "802acf025b55dcfa6c69ffe12629dd45300fc28cbb531d2a7e858cf4be17ce65", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_scheduling_threshold_eval.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d30294ab817479ff8a7e189089c1e351dbadad091b63b668ab42b5c563853cd8", - "review_fingerprint": "d30294ab817479ff8a7e189089c1e351dbadad091b63b668ab42b5c563853cd8", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "按平台阈值决定账号是否自动停调的纯函数评估器(OpenAI 5h/7d、Anthropic 5h/7d 与 Fable 7d_oi、Grok header 窗口、CN Coding Plan 5h/weekly/monthly,取最晚重置的命中窗口)。下游相对上游只改 openAIThresholdCandidate:不再直读 codex_5h/7d_used_percent 与 reset_at,而是从共享读模型 OpenAIQuotaWindows 中按 WindowMinutes(300/10080)精确匹配、跳过已过期窗口,每个窗口带各自的 ResetsAt;已知上游截止时间在快照变旧时仍然有效,仅无截止时间的建议性停调才要求快照新鲜。修正了上游把陈旧快照一律忽略的行为,且未在窗口间共享截止时间。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (38 lines): openAIThresholdCandidate L250-L272 rewritten to iterate OpenAIQuotaWindows(extra, now) with per-window match on WindowMinutes and Expired, stale check only when observed.ResetsAt == nil.", - "Call chain: OpenAIQuotaWindows in service/account_quota_windows.go L106-L128 and readQuotaWindow L130-L162 build one AccountQuotaWindow per primary/secondary (or legacy 5h/7d) with its own reset_at/reset_after_seconds; deadlines are not shared across windows. Decision consumers: pickLatestResetSchedulingCandidate L386-L401 requires candidate.until != nil.", - "Unchanged upstream parts (Anthropic/Grok/CN candidates, override parsing L123-L170, identity trust L193-L223) read in full; no behavior claim beyond static reading." - ] - }, - { - "path": "backend/internal/service/account_scheduling_threshold_eval_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a103248660705290453b8fbd1c72915b12d7a5c174fade2af5827654f98ca814", - "review_fingerprint": "a103248660705290453b8fbd1c72915b12d7a5c174fade2af5827654f98ca814", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "阈值评估器的单元测试(//go:build unit)。下游相对上游把 OpenAISkipsStaleSnapshot 改为 OpenAIKeepsKnownDeadlineFromStaleSnapshot:codex_usage_updated_at 已 2 小时旧但 codex_5h_reset_at 仍在未来时应停调;删除 reset_at 后同一快照不再停调(建议性停调需要新鲜证据)。这直接证明 account_scheduling_threshold_eval.go 的下游修正。其余上游用例(最晚重置窗口优选、Codex 快照身份不一致忽略、Anthropic 过期 5h 忽略、Fable 7d_oi 独立评估、账号级阈值覆盖/100 关闭/小数取整、Gemini/Kiro/Antigravity 不停调、Grok 仅用 header 窗口)静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (7 lines): L166-L185 renamed test, asserts ShouldPause true with stale sample + future deadline, then false after delete(account.Extra, \"codex_5h_reset_at\").", - "Other tests read: L13-L39, L41-L68, L70-L97, L99-L134, L136-L164, L187-L249, L251-L351, L353-L420, L422-L476.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/account_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3b24345bae935f11b60bca0c6fdda3d408388041a8ff69e49765c9a9f749e314", - "review_fingerprint": "3b24345bae935f11b60bca0c6fdda3d408388041a8ff69e49765c9a9f749e314", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "基础 AccountService(Create/Update/Delete/List、AccountRepository 与批量更新接口、OAuth 刷新分页契约)。下游相对上游新增 11 行:Create/Update 先对 credentials 调用 NormalizeAccountCredentialBaseURLs;Create 时从 Extra 删除 UpstreamModelContextCapacities/ModelContextOverrides/UpstreamModelMetadata 三个受管键,Update 时删除请求中的这三个键并回填当前存储值,使模型上下文容量/覆盖只能经专用的 ModelContextOverridesPatch 路径写入而不会被通用 Extra 覆盖。通用账号 CRUD 机制,无插件业务规则;静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (11 lines): L226 and L336 NormalizeAccountCredentialBaseURLs; L248-L250 delete managed extra keys on create; L348-L353 strip and preserve managed keys on update.", - "Unchanged upstream content read in full: repository interfaces L50-L154, request DTOs L175-L204, group validation L440-L471, TestCredentials platform switch L509-L535.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/account_test_models_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "076008cb1244f96cf5348b56b1d2a9d11211e27ae519bbff7e3682ffa578f68d", - "review_fingerprint": "076008cb1244f96cf5348b56b1d2a9d11211e27ae519bbff7e3682ffa578f68d", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_prompt.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "77fc9bad2bc4f9f896efd05dd5b1096ea7c2287a7d5c47c5e570b8258f0b93ac", - "review_fingerprint": "77fc9bad2bc4f9f896efd05dd5b1096ea7c2287a7d5c47c5e570b8258f0b93ac", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_prompt_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2042fb7413243738c3229bd534525a87d431dfa093d1e54c256e5c45467d2c82", - "review_fingerprint": "2042fb7413243738c3229bd534525a87d431dfa093d1e54c256e5c45467d2c82", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_reasoning.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "2b347b5a04c4467be2baf39c4de944306df3dfd98ece12fc7a428a14c50df30c", - "review_fingerprint": "2b347b5a04c4467be2baf39c4de944306df3dfd98ece12fc7a428a14c50df30c", - "review_status": "reviewed", - "decision": "adapter", - "owner": "account-tools", - "reason": "Full-file review and one caller change: actual-account policy scope for explicit reasoning options, preserving existing wire capability discovery and empty defaults.", - "evidence": [ - "Empty effort still returns before plugin invocation; account availability and model/wire reasoning levels remain host-derived.", - "Nonempty selection now uses the account-scoped adapter and cannot bypass rollout through AccountID=0.", - "Request field encoding and effective reasoning context storage were not changed." - ] - }, - { - "path": "backend/internal/service/account_test_reasoning_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "beb9764a0d66fc50fd7b34deba91347fa4bad4eaa3c28588398a7651a00a2572", - "review_fingerprint": "beb9764a0d66fc50fd7b34deba91347fa4bad4eaa3c28588398a7651a00a2572", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_reasoning_wire_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a0446c211151f766224d963407de3dcc7708e59d6cf3ac476b59a5d13ce27ace", - "review_fingerprint": "a0446c211151f766224d963407de3dcc7708e59d6cf3ac476b59a5d13ce27ace", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_service.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "915d4d7fb9a898d8799ea6320be2e9067256eaca462c3ef0c9ed9343ec227974", - "review_fingerprint": "915d4d7fb9a898d8799ea6320be2e9067256eaca462c3ef0c9ed9343ec227974", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_service_cn_adaptive.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "bea2cae38f2a2857c7fe3facca1c49a90f35b75741cf6ddaf087b2cd8f9a2634", - "review_fingerprint": "bea2cae38f2a2857c7fe3facca1c49a90f35b75741cf6ddaf087b2cd8f9a2634", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_service_openai_compact_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2bd424d6592b24e996d9e199a65b9e3c6b3d3066d5feb2aaffbf3f9bc4fb3b5b", - "review_fingerprint": "2bd424d6592b24e996d9e199a65b9e3c6b3d3066d5feb2aaffbf3f9bc4fb3b5b", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_service_openai_image_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2227bc9f7b3dcb87611097e12d8da6a6107a508ed56f35215969937bec3cc182", - "review_fingerprint": "2227bc9f7b3dcb87611097e12d8da6a6107a508ed56f35215969937bec3cc182", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_service_openai_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "11e1244e657f55da00b03d53c49bb8f2889ece5810a12f0d1990684a6c004b00", - "review_fingerprint": "11e1244e657f55da00b03d53c49bb8f2889ece5810a12f0d1990684a6c004b00", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_test_service_opencode_go.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "8eb08f3a6817635c0da8276bff2d37411104c95c9c857b843cb89aa020af0c14", - "review_fingerprint": "8eb08f3a6817635c0da8276bff2d37411104c95c9c857b843cb89aa020af0c14", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_traffic_observe.go", - "candidate_owner": "admin-observability", - "role": "source", - "present": true, - "content_sha256": "8d409c60ece970db70015862735269253304033afd6913beb0d1b16ba4515ddd", - "review_fingerprint": "8d409c60ece970db70015862735269253304033afd6913beb0d1b16ba4515ddd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Full-file review: Begin and Snapshot now admit by actual account; host counters and exactly-once finishing behavior are preserved.", - "evidence": [ - "Read all 245 final lines. Begin accepts *Account already selected by the caller, resolves its policy before cache.Begin and stores only the admitted account ID/protocol and captured classification.", - "Snapshot accepts the already-loaded *Account, uses the same account-specific policy once, and returns ErrAccountTrafficTelemetryUnavailable without reading counters for missing/disabled/out-of-scope identity.", - "Enabled is explicitly documented as an unscoped management indicator, not account admission. Source search finds no production handler call to Enabled after this change.", - "AccountTrafficObserveCache remains the raw ID-based storage interface. The Finish function body is byte-for-byte identical to HEAD after newline normalization: captured DecisionTable, sync.Once, detached two-second context, one outcome write and nil-safety are unchanged.", - "All protocol/outcome validation, bounded Redis TTL/timeout, logging and no-business-request-gating behavior remain unchanged." - ] - }, - { - "path": "backend/internal/service/account_usage_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "eded97679871ec2aeb5cca42652f3f2e3022e7047f724bab058b3c9275132b94", - "review_fingerprint": "eded97679871ec2aeb5cca42652f3f2e3022e7047f724bab058b3c9275132b94", - "review_status": "pending" - }, - { - "path": "backend/internal/service/account_usage_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a72677e6995d9dc1f40ec5a27b557b6b3e845cd06f1876de9cba0e10b1712033", - "review_fingerprint": "a72677e6995d9dc1f40ec5a27b557b6b3e845cd06f1876de9cba0e10b1712033", - "review_status": "reviewed", - "decision": "upstream-covered", - "owner": "core-quota-and-protocol", - "reason": "上游已有的用量服务测试;下游相对上游仅在三处 t.Fatal 后追加 return(静态分析空指针提示),断言内容与上游完全一致。测试断言:限流账号或缺 5h/7d 快照或 WSv2 账号快照过期时触发 Codex 刷新;spark 影子的过期判定不受 WSv2 门控而普通账号受之;带 x-codex-* 头的 429 也能提取 5h/7d 用量;探针快照只写 Extra 不写运行时限流;已耗尽的 codex extra 不被提升为 RateLimitResetAt;过期窗口用量归零。无下游特有内容;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (3 lines): `return` added after t.Fatal at L221, L240, L255 only.", - "Tests read: L34-L67, L71-L116, L118-L142, L144-L171, L173-L207, L209-L261; stub repo L10-L32.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/account_usage_session_window_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a012b8b93aeb42911dd51f6e846d5207d792e7b43622b0b6ebff0eeea086aade", - "review_fingerprint": "a012b8b93aeb42911dd51f6e846d5207d792e7b43622b0b6ebff0eeea086aade", - "review_status": "reviewed", - "decision": "upstream-covered", - "owner": "core-quota-and-protocol", - "reason": "上游已有测试;下游相对上游仅在两处 t.Fatal 后追加 return,断言不变。测试断言:estimateSetupTokenUsage 对已过期 SessionWindowEnd 把利用率/ResetsAt/剩余秒数归零,对未过期窗口保留 0.53→53% 与 ResetsAt;syncActiveToPassive 在 FiveHour.ResetsAt 存在时精确按 accountID=42 调用一次 UpdateSessionWindowEnd,ResetsAt 缺失时不调用。无下游特有内容;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (2 lines): `return` after t.Fatal at L56 and L83.", - "Tests read: L42-L67, L69-L94, L96-L121, L123-L137; recording repo L11-L40.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/account_wildcard_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d1563b165aa38c383427249262e2b1278577a6b3a302023fe43a3a96dbaa5e73", - "review_fingerprint": "d1563b165aa38c383427249262e2b1278577a6b3a302023fe43a3a96dbaa5e73", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "上游已有的 model_mapping 通配符/缓存/Antigravity/Google One 测试集;下游相对上游新增 TestLegacyCindyRuntimeCompatibilityMapsAliasesAndPreservesDirectLiveModels:对 platform=openai、base_url=https://api.laxarouter.ai 的 legacy Cindy APIKey 账号,断言兼容别名 gpt-5.4-mini 经插件目录解析为 openai/gpt-5.6-luna 且视为支持,直连 live 模型原样保留,gpt-5.4 与 gpt-5.6-sol 不被支持,账号级过期映射(sol)仍作为数据返回但 ResolveCindyCapability 拒绝 sol 路由,terra 继续走账号映射(legacy 兼容不放开更大的 Cindy 目录)。这证明的是 account.go 中宿主→cindy-provider 目录桥接的边界,其余用例为上游内容;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (43 lines): import require L10; new test L595-L635 exercising Account.IsModelSupported/ResolveMappedModel/GetMappedModel and ResolveCindyCapability.", - "Upstream tests read in full: L13-L33 Grok runtime mapping cache, L35-L157 wildcard matching, L159-L325 IsModelSupported incl. DeepSeek whitelist, L327-L423 GetMappedModel, L425-L503 Antigravity 3.1 pro aliases, L505-L593 ResolveMappedModel, L637-L797 Antigravity/Google One defaults and cache invalidation.", - "Bridge subject: account.go L915-L934/L969-L986 -> service/cindy_capability_catalog.go wrappers -> plugin registry. Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/admin_account.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a093b3f9180aca978e757c9cde222f575bdb5af498099f84152bb7492448b6c1", - "review_fingerprint": "a093b3f9180aca978e757c9cde222f575bdb5af498099f84152bb7492448b6c1", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_account_cindy_probe.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "9c7af868bde1568f91cef48e532bb77a96c75ac78f7eb6cd8efe52bacbd5efcd", - "review_fingerprint": "9c7af868bde1568f91cef48e532bb77a96c75ac78f7eb6cd8efe52bacbd5efcd", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_account_cindy_probe_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4162cf4b95fd19aea4c8518df7bbfd72bfe8ace5fce9639e0ca14c62150706c9", - "review_fingerprint": "4162cf4b95fd19aea4c8518df7bbfd72bfe8ace5fce9639e0ca14c62150706c9", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_account_codex_ticket_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1647e9b7696e217497256a6ffc45d5d47e69a0b418ad520eb28e1ea181063ceb", - "review_fingerprint": "1647e9b7696e217497256a6ffc45d5d47e69a0b418ad520eb28e1ea181063ceb", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "两条服务层测试,证明管理端账号 CRUD 不能写入或覆盖服务端托管的门票键:UpdateAccount 两次提交(带伪造 codex_turn_ticket:gpt-6-astra 摘要 / 不带该键)后账号 extra 中该键仍等于原 CodexTicketRecord 且 custom 键随提交更新;UpdateAccountExtra 提交 state=spoofed 后仓储内门票不变;buildAccountForCreate 丢弃创建输入里的 codex_turn_ticket:custom 而保留 custom。被测代码是 admin_account.go 中对 MergeOpenAICodexTicketExtra 的四处调用(L468 创建、L904 更新时以库内 account.Extra 为准、L1149 UpdateAccountExtra、L1194 BulkUpdate 均清空提交侧门票键),属宿主管理端 CRUD 的输入净化机制,不涉及 codex-runtime 的采集/续期执行。上游无此文件。测试仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S62-codex-ticket-T1-review.json", - "L10-L25 TestUpdateAccountPreservesCodexTicketOnEdit:ticketTestAccount(41)(openai_codex_ticket_test.go L26)+ fakeCodexTicketState(292)(同文件 L20)构造带 openAICodexTicketExtraKey(model) 的账号,仓储桩 upstreamBillingProbeAccountRepo(upstream_billing_probe_test.go L21);对两种 Extra 输入各断言 updated.Extra[key]==ticket 且 custom==true;随后 UpdateAccountExtra 提交 spoofed 后 repo.accounts[41].Extra[key] 仍为原票。", - "L26-L31 TestCreateAccountDropsUserSuppliedCodexTickets:buildAccountForCreate(PlatformOpenAI/OAuth, {codex_turn_ticket:custom, custom}) → NotContains 门票键、custom 保留(admin_account.go L467-L468 MergeOpenAICodexTicketExtra(accountExtra, nil))。", - "不宣称:未覆盖 BulkUpdateAccounts 路径(无断言);未验证真实仓储行锁(由 repository 侧测试覆盖);测试未执行。" - ] - }, - { - "path": "backend/internal/service/admin_account_model_context_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "70aae018428d2524adfb525b99c6132edf0dedd1dbd43ab9bcbe37a82289932f", - "review_fingerprint": "70aae018428d2524adfb525b99c6132edf0dedd1dbd43ab9bcbe37a82289932f", - "review_status": "reviewed", - "decision": "plugin", - "owner": "model-policy", - "reason": "新增测试,经宿主管理员账号 create/update/bulk 路径验证 model-policy 的按账号模型上下文窗口覆盖(ModelContextOverrides)特性:类型化且原子落库、UpstreamModelContextCapacities/Metadata 与原始 ModelContextOverrides 运行态键不可经 Extra/Bulk 注入、非法窗口值与受保护账号类型(OAuth/setup token)在持久化前被拒、ModelContextOverridesPatch 绝不 JSON 序列化。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAdminCreateAccountModelContextOverridesAreTypedAndAtomic / ...PatchPreservesManagedState / ...ValidationRejectsBeforePersistence / ...CannotInjectModelContextRuntime (L11-L108)", - "Subject = model-policy per-account context override applied through core admin CRUD; asserts injection resistance (L99-L107) and json:'-' on ModelContextOverridesPatch (L110-L115)", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/admin_account_taxonomy.go", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "017d5d8247ebc1f335641f8c03debbcc2ac71f488c2c5d1d4a9054d9ad48a39b", - "review_fingerprint": "017d5d8247ebc1f335641f8c03debbcc2ac71f488c2c5d1d4a9054d9ad48a39b", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_account_taxonomy_test.go", - "candidate_owner": "account-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8f4cd2ac6c4caa07d0ddd68c45861dcd4f0a9919b9422a7dd7421be1053d9f05", - "review_fingerprint": "8f4cd2ac6c4caa07d0ddd68c45861dcd4f0a9919b9422a7dd7421be1053d9f05", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "Full-file test review with three new targeted cases; existing unrelated console/facet tests were left unexecuted.", - "evidence": [ - "Read the original 137 lines and all 94 new lines. Four synthetic policy replies replace folder 7 with 8, clear folder 7, add tag 9, or omit tag 6. Input is account 42/folder 7/tags [5,5,6]; every case must return ErrExtensionOperationUnavailable and nil account before SQLMock permits any database Begin.", - "The real policy still transforms [6,5,6] into [6,5], which the host intent guard accepts; empty folder/tag clear is accepted by the invariant guard.", - "With processExtensionOperations=nil, SetAccountTaxonomy and BulkUpdateAccountTaxonomy return errors before touching a nil database, proving no host business fallback.", - "For each global delete name, existing ResourceDescriptors.Available and ValidateResourceAccounts agree: only wildcard platform/type with 100% rollout succeeds; platform-restricted, type-restricted and 99% bindings fail.", - "Existing normalization, derived status/plan, Cindy identity, ban/balance independence and facet tests were read but not rerun." - ] - }, - { - "path": "backend/internal/service/admin_cindy_balance.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "afa6fa2b72d03c1996c50ecaec9ce86ab3a76639f0cea7050e00d2bc61253c58", - "review_fingerprint": "afa6fa2b72d03c1996c50ecaec9ce86ab3a76639f0cea7050e00d2bc61253c58", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_cindy_balance_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c40215e5cdc4493f12aa4fcbf64f42c368e96d9548327f177c921f4c96907cf9", - "review_fingerprint": "c40215e5cdc4493f12aa4fcbf64f42c368e96d9548327f177c921f4c96907cf9", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_cindy_duplicate_inventory.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "1f159be694fb8ffac1588a95d4285753f7c8dde0ec92e1d545fd12c7b3984a5e", - "review_fingerprint": "1f159be694fb8ffac1588a95d4285753f7c8dde0ec92e1d545fd12c7b3984a5e", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "全文复核32行适配:ListByPlatform后仅bound view用同一宿主matcher过滤base/preset/账号bucket,再交原插件聚合;无view直接保持原候选语义。nil repo仍返回空列表,读取/准入错误不吞;独立GET没有公共search参数,不新增查询协议,不向插件输送范围外事实。新增实际先红后绿反例证明5候选收窄到2,原core正控未变。", - "evidence": [ - "artifacts/evidence/v027-account-view-integration-review.json#verification", - "Current complete source read plus exact frozen/current SHA verification; no full-application runtime claim." - ] - }, - { - "path": "backend/internal/service/admin_cindy_group_split.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "222351acf7d91a1fb742b66ac236ee9a0c423313719ae3d9aafc264ae1c7c500", - "review_fingerprint": "222351acf7d91a1fb742b66ac236ee9a0c423313719ae3d9aafc264ae1c7c500", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_cindy_group_split_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "40e44ed76becb0e6915e186359ff95583e2b9313a69fcd1f9776b43645c912fe", - "review_fingerprint": "40e44ed76becb0e6915e186359ff95583e2b9313a69fcd1f9776b43645c912fe", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_group.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ac5886e8d4d0dab0b86364e2cf61e6b0a1c943af69227ba8545861633742fd8f", - "review_fingerprint": "ac5886e8d4d0dab0b86364e2cf61e6b0a1c943af69227ba8545861633742fd8f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主管理员分组 CRUD 服务实现(Create/Update/Delete/Composite 路由/复制账号等)。下游相对上游新增:以 ResolveGroupProviderIdentity 解析并落库 platform/wirePlatform/providerProfile,providerGroupIdentityCompatible 与 validateProviderIdentityAccountsForGroup 校验分组与成员/复制源身份一致,Cindy 分组禁止配置 fallback,AllowLive 改用 EffectiveWirePlatform 判定,GetGroup 时 hydrateStrictCindyGroupIdentity。cindy-provider 身份规则本体在核心 provider_identity.go,本文件仅编排。静态阅读,未执行测试/构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "CreateGroup L382-L681 & UpdateGroup L768-L1185: ResolveGroupProviderIdentity, providerGroupIdentityCompatible/validateProviderIdentityAccountsForGroup, PlatformCindy fallback bans (L504,L515,L962,L987), AllowLive gated on EffectiveWirePlatform (L640,L1074)", - "Channel cache invalidated on platform change (L1108); provider-identity helpers live in provider_identity.go so no plugin duplicate executor", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/admin_group_duplicate.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "272b498fb5dfdc640a7351a80a85ab10239cc0fa1a1a8497e6ba2090e2eaee0a", - "review_fingerprint": "272b498fb5dfdc640a7351a80a85ab10239cc0fa1a1a8497e6ba2090e2eaee0a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主分组复制机制(cloneGroupForDuplicate 深拷贝 + DuplicateGroup 幂等重试按名/操作ID)。下游相对上游唯一改动是克隆体不再复制 ProfitControlEnabled/ProfitMinMargin/ProfitSafetyBuffer——与利润控制运行期退役一致(openai_profit_control.go profitControlRuntimeEnabled=false,认证快照亦恒置 false/0),属协调一致的清理而非缺陷;其余为核心复制编排。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "cloneGroupForDuplicate L96-L161 no longer copies ProfitControl* (diff removed 3 lines); DuplicateGroup L193-L239 idempotent retry on ErrGroupExists", - "Consistent with profit-control retirement: openai_profit_control.go:74-77 profitControlRuntimeEnabled=false and api_key_auth_cache_impl.go forces ProfitControl false/0 in snapshots", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/admin_group_platform_cache_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c105ad8f8a0a8a5e61898f8240c6e50ed514256838b6e00642a06f109a846ae8", - "review_fingerprint": "c105ad8f8a0a8a5e61898f8240c6e50ed514256838b6e00642a06f109a846ae8", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "单元测试(//go:build unit)验证核心行为:UpdateGroup 在分组 platform 变化时失效渠道缓存(channelCacheInvalidator)、同平台或未传 platform 不失效、缺失失效器时不 panic。下游 delta 仅为 groupPlatformRepoStub 新增 GetAccountIDsByGroupIDs 空桩以适配 GroupRepository 接口扩展。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestUpdateGroupInvalidatesChannelCacheOnPlatformChange L41-L81 asserts wantCalls per platform transition; TestUpdateGroupWithoutChannelCacheInvalidator L84-L90", - "Downstream delta = stub GetAccountIDsByGroupIDs L29-L31 for the new repo method consumed by validateProviderIdentityAccountsForGroup", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/admin_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "8eedcea90fb0a103f8e7bb5bfde04f5a8456cafbe24ac24fddf2885c81e59298", - "review_fingerprint": "8eedcea90fb0a103f8e7bb5bfde04f5a8456cafbe24ac24fddf2885c81e59298", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_service_bulk_update_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7f3495db616150ae9724a6d0ef1ce7ecb3690251222a4becb08120b4a0833074", - "review_fingerprint": "7f3495db616150ae9724a6d0ef1ce7ecb3690251222a4becb08120b4a0833074", - "review_status": "pending" - }, - { - "path": "backend/internal/service/admin_service_composite_group_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "26a2a4269f90f7f6df900c2ba1a988f2d705a96e918fcf4efca1f73fbb955d9f", - "review_fingerprint": "26a2a4269f90f7f6df900c2ba1a988f2d705a96e918fcf4efca1f73fbb955d9f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "核心 composite 分组测试套件:从具体平台分组复制账号(create/update)、账号可绑定 composite 组、composite 模型候选合并具体账号 model_mapping、独立 CN 分组保留 Claude 默认候选。下游 delta 为 accountRepoStubForCompositeModelsList 新增 GetByIDs,以支撑 CreateGroup/UpdateGroup 新增的 provider 身份账号校验。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAdminService_CreateCompositeGroupCopiesAccountsFromConcreteGroups L33-L81; UpdateComposite... L83-L133; CompositeModelsListCandidates L185-L226; CNProvider...KeepClaudeDefaults L230-L237", - "Downstream delta = GetByIDs stub L23-L31 for the provider-identity account validation path", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/admin_service_group_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f8f2906fff6e961dc37ecc6846a1bb5658442e00b0ed55fc195ddba298cb428f", - "review_fingerprint": "f8f2906fff6e961dc37ecc6846a1bb5658442e00b0ed55fc195ddba298cb428f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "核心管理员分组服务测试套件(2424 行):simple mode 字段归一化、图片/视频定价、批量图片 hold>=discount 不变量、峰值倍率、推理强度映射三态、fallback 环检测与无效请求 fallback、composite 路由、Codex manifest 校验。下游 delta 新增 cindy 严格身份 hydrate(GetGroup 经 ClassifyStrictCindyGroup)与 cindy 目录候选测试,并把 GetAccountIDsByGroupIDs 桩由 panic 改 nil 以适配 provider 身份账号校验、simple-mode 用例以 ModelAllowlist 替换已收敛移除的 ProfitControl 字段。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAdminServiceGetGroupHydratesStrictCindyIdentityFromCompleteMembership L58-L87; ...GetGroupModelsListCandidatesUsesCindyCatalog L541-L562; Codex manifest validation L2242-L2350; fallback cycle L1596-L1616", - "Stubs GetAccountIDsByGroupIDs now return nil,nil (L376,L1682,L1753) instead of panic to support provider-identity account validation", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/admin_service_spark_shadow_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f5a1dd7ee89c168e1f5f44378eb0ff6e11a69fe041855530f8e76eacb1da3234", - "review_fingerprint": "f5a1dd7ee89c168e1f5f44378eb0ff6e11a69fe041855530f8e76eacb1da3234", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "核心 spark 影子(凭据影子)账号不变量测试套件:影子恒不持鉴权凭据(create/update/bulk/persist 各路径 fail-closed)、一母一影(409)、级联删除、proxy 恒继承母账号并传播、type 不可变、并发竞态与绑组失败回滚、reset-quota/隐私对影子早返。下游 delta 仅为 sparkShadowValidatingGroupRepoStub 新增 GetByID(返回 OpenAI 组)以支撑 UpdateAccount 携带 GroupIDs 时的 provider 身份组绑定校验。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestCreateShadow L124-L158; credential guards RejectsCredentialWriteToShadow (single L652-L690, bulk L557-L578); bind-failure rollback L838-L856", - "Downstream delta = GetByID stub L765-L770 returning Group{Platform: OpenAI} for the provider-identity binding path", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/agent_cc_stream_contract_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "53b0cad519778e39fabe2c927244c7c71548c90c0505214309708d58a9dc17ad", - "review_fingerprint": "53b0cad519778e39fabe2c927244c7c71548c90c0505214309708d58a9dc17ad", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增网关契约测试(OpenAIGatewayService):scanCCStream(chat-completions→responses 桥接)要求语义终止——EOF 早于 finish、哨兵无 finish、错误帧、畸形帧、HTML、仅 usage 均判失败;responses 桥接对未产出输出的中断流保持可 failover(元数据前缀缓冲不下发)、已下发 terminal 不可重放。核心网关协议正确性。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAgentCCStreamRequiresSemanticTermination L20-L47 termination table; TestAgentResponsesBridgeDoesNotCompleteBrokenStreams L49-L76 asserts no response.completed + buffered vs delivered UpstreamFailoverError", - "Subject OpenAIGatewayService.scanCCStream / Forward (core gateway protocol)", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/agent_raw_stream_contract_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "06dda75eae361f1fd0d297f23f5b03a73bd1221a8b3ae51ba75a038bbdf3aeb4", - "review_fingerprint": "06dda75eae361f1fd0d297f23f5b03a73bd1221a8b3ae51ba75a038bbdf3aeb4", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增网关契约测试:forwardAsRawChatCompletions 要求语义终止(仅哨兵/仅 usage/错误帧/畸形帧不算完成且缓冲可 failover;截断但有内容或未闭合 tool arguments 视为已下发);上游读取 DeadlineExceeded 不得误判为客户端取消(ClientDisconnect=false 且不可 failover)。核心网关协议正确性。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAgentRawChatRequiresSemanticTermination L18-L47 wrote/failover matrix; TestAgentRawUpstreamTimeoutIsNotClientCancellation L49-L64", - "Subject OpenAIGatewayService.forwardAsRawChatCompletions", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/agent_request_capabilities_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "473e5a8fabb4f9dbea61465e61aa28c3f398d1dbff4931b7e452574110db08af", - "review_fingerprint": "473e5a8fabb4f9dbea61465e61aa28c3f398d1dbff4931b7e452574110db08af", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增测试:OpenAIResponsesRequireNativeUpstream 判定何时必须走原生 responses 上游——null 默认(conversation/previous_response_id/background)忽略;conversation/previous_response/background、hosted 工具(file_search)、hosted 历史(web_search_call)、不透明 reasoning 触发原生;portable function 与 additional_tools 不触发。核心网关请求路由正确性。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAgentRequestCapabilitiesIgnoreNullDefaults L11-L31 native-vs-portable request-shape table", - "Subject OpenAIResponsesRequireNativeUpstream (core gateway routing)", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/agent_selection_diagnostics_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "96aa17b1386419afef52708bd818f8082e209ba5926f902b2e8a2319225df89c", - "review_fingerprint": "96aa17b1386419afef52708bd818f8082e209ba5926f902b2e8a2319225df89c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增测试:selectAccountWithLoadAwareness 在无可用账号时保留排除原因诊断(model_not_supported/runtime_blocked/pool 计数、RetryAfterSeconds 来自 runtime block 到期),错误可经 GetOpenAISelectionDiagnostics 解析。核心调度诊断正确性。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAgentLoadAwareSelectionPreservesExclusionReasons L13-L34 asserts Rejected map (model_not_supported=1, runtime_blocked=1) + RetryAfterSeconds~60", - "Subject OpenAIGatewayService selection + BlockAccountScheduling (core scheduling)", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/agent_upstream_error_scope_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bf2ea117ad9a2f1fd21449798bb399466e5504c0ab4095e65a1af4c47a5fa6ad", - "review_fingerprint": "bf2ea117ad9a2f1fd21449798bb399466e5504c0ab4095e65a1af4c47a5fa6ad", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增测试:上游 400 分类(嵌套 upstream_error 可 failover,客户端校验/带 param/仅数字/continuation 不 failover);balance_insufficient 预算拒绝不得变成账号鉴权冷却(不 runtime-block、切下一账号)、且预算分类先于 HTTP failover(402/403 均 failover,type 与 code 必须都命中)。核心网关 failover/预算正确性。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAgentReportedUpstream400IsNotClientValidation L13-L29; ...BudgetRejectionDoesNotBecomeAccountAuthCooldown L31-L41; ...BudgetClassificationPrecedesHTTPFailover L43-L56", - "Subject OpenAIGatewayService shouldFailoverOpenAIUpstreamResponse / newOpenAIAccountFailoverError / isOpenAIRequestBudgetRejection", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/anthropic_apikey_auth.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0d42753ad5b9f310615b776c111464f53b604f3e5c714cac0a23ebcf625655d8", - "review_fingerprint": "0d42753ad5b9f310615b776c111464f53b604f3e5c714cac0a23ebcf625655d8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "决定 Anthropic API-key 账号出站认证头用 x-api-key 还是 Authorization: Bearer:GetAnthropicAPIKeyAuthScheme 只对 Anthropic 平台或 CN 提供商的 API-key 账号读取 extra.anthropic_apikey_auth_scheme,isOllamaCloudAnthropicAuthBaseURL 按本次实际 base_url 强制 Ollama Cloud 走 Bearer,这两段与上游 aea725f 完全一致。下游唯一改动是在 setAnthropicAPIKeyAuthHeader 最前面新增分支:IsCindyRuntimeCompatibleAPIKeyAccount(platform,type,credentials) 为真时强制 Bearer,并给 Cindy/Ollama 两个分支补了 account != nil 保护。属于网关出站协议层的通用机制;Cindy 例外只是调用 core 的身份谓词做线协议判定,plugins/cindy-provider 内没有任何认证头或 host 判定代码(仅 manifest 的 base_url),不构成二次执行器。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S21-svc-gateway-billing-1-review.json", - "L20-L34 GetAnthropicAPIKeyAuthScheme: nil-safe receiver, returns x_api_key unless Type==api_key AND (Platform==anthropic OR IsCNProvider()) AND extra value is exactly authorization_bearer; L41-L43 Ollama Cloud base_url normalization reuses isOllamaCloudBaseURL (ollama_cloud_usage.go:1045).", - "git diff aea725f: single hunk L51-L62 adds the IsCindyRuntimeCompatibleAPIKeyAccount Bearer branch (predicate defined in cindy_identity.go: PlatformCindy or legacy PlatformOpenAI projection with https://api.laxarouter.ai base_url) plus account!=nil guards; the L63 fallback is already nil-safe via the method's a==nil check.", - "Call chain (rg, non-test): gateway_upstream_request.go:136, gateway_anthropic_passthrough.go:463, gateway_count_tokens.go:463/579, openai_gateway_messages_anthropic_native.go:202, upstream_models.go:1023, account_test_service*.go — all pass the request's actual account and its selected base URL, so the header decision is bound to the scheduled account.", - "rg over plugins/cindy-provider for x-api-key / Bearer / IsCindyAPIKeyAccount / cindyAPIHost: no hits in Go code (only manifest.source.json base_url and catalog comments), so no duplicated executor. No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/antigravity_gateway_compat_stream.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "78c6b825d3b5c2985db5463600f693214c10a2fb82d559dd056ac9498e8f0bde", - "review_fingerprint": "78c6b825d3b5c2985db5463600f693214c10a2fb82d559dd056ac9498e8f0bde", - "review_status": "pending" - }, - { - "path": "backend/internal/service/antigravity_gateway_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "92fcce5a18b7da67a7174807014a51fe7b16c42193ce7a59905839e5e38c3f3b", - "review_fingerprint": "92fcce5a18b7da67a7174807014a51fe7b16c42193ce7a59905839e5e38c3f3b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Antigravity 平台网关服务的基础部分:限流/智能重试常量、AccountSwitchError/PromptTooLongError 信号、错误策略应用(applyErrorPolicy 先按模型级限流再走 RateLimitService)、模型映射 mapAntigravityModel、project_id 解析、TestConnection 复用 antigravityRetryLoop、v1internal 请求包装/解包与身份提示词注入。下游相对上游 aea725f 只改了 TestConnection 及两个测试请求构造器:新增可变参数 prompts,先用 ValidateAccountTestPrompt(UTF-8 且 ≤8192 字)校验,再用 resolveAntigravityTestPrompt(无 prompt 时仍为 \".\")和 accountTextTestOutputLimit(有自定义 prompt 时 maxOutputTokens 1024,否则 1)构造 Gemini/Claude 测试体。这是宿主网关协议层把管理员自定义测试提示词透传到上游的传输改动,提示词策略本身的插件钩子(account_test_prompt.go 的 test.prompt 操作)不在本文件;plugins/account-tools 中无重复实现。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S21-svc-gateway-billing-1-review.json", - "Unchanged upstream body: L22-L66 retry/rate-limit constants, L74-L78 global modelCapacityExhaustedUntil map guarded by RWMutex (bounded by model names), L210-L256 applyErrorPolicy + handleAntigravityModelRateLimitBeforePolicy keyed on p.account.ID / groupID / sessionHash, L261-L292 mapAntigravityModel, L300-L314 resolveAntigravityProjectID, L576-L644 identity patch injection and v1internal wrap/unwrap.", - "git diff aea725f (23+/9-): L344-L354 prompts variadic + ValidateAccountTestPrompt loop (the extra prompts[0] re-check at L350-L354 is redundant with the loop but harmless), L379/L381 pass prompts to builders, L454-L475 buildGeminiTestRequest uses resolveAntigravityTestPrompt/accountTextTestOutputLimit, L480-L497 buildClaudeTestRequest marshals the prompt as Claude content.", - "Call chain: only non-test caller is account_test_service.go:2545 (s.antigravityGatewayService.TestConnection(ctx, account, testModelID, prompts...)); helpers defined in account_test_prompt.go L15/L27/L59, where validateAccountPromptExtension routes prompt policy to the account-tools extension operation test.prompt — so policy stays with the plugin hook, this file is transport only.", - "rg over plugins/account-tools Go code for ValidateAccountTestPrompt/TestPrompt: no duplicate executor. Test requests are sent through antigravityRetryLoop with the passed account's own access token and project_id, so the probe is bound to the actual account. No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/api_key.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c1767a380a648a000fd54f4d8fa04593ed6c9a37a34f4c74c74e6fedae5c2a1a", - "review_fingerprint": "c1767a380a648a000fd54f4d8fa04593ed6c9a37a34f4c74c74e6fedae5c2a1a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主 API Key 领域模型与常量:状态/限流窗口常量、APIKey 结构体及配额/限流窗口过期辅助方法、APIKeyListFilters。下游相对上游新增 Purpose(user/release_acceptance)与 LeaseID 字段及常量,支撑“发布验收”租约 Key。纯类型与辅助逻辑,无业务执行分支。静态阅读,未执行构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "APIKey struct L33-L70 adds Purpose/LeaseID (L40-L41); APIKeyPurpose* consts L16-L17; quota/window helpers L72-L143", - "Fields are plain metadata on the core APIKey model; no plugin business logic here", - "File statically reviewed only; no build run." - ] - }, - { - "path": "backend/internal/service/api_key_auth_cache.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "65420f11d1a0a766af8a51e3d3282c7a0088d1d86bb5d63abf0667652e5d560b", - "review_fingerprint": "65420f11d1a0a766af8a51e3d3282c7a0088d1d86bb5d63abf0667652e5d560b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "API Key 认证缓存快照 DTO(APIKeyAuthSnapshot/User/Group snapshot + 负缓存条目)。下游相对上游在 group 快照新增 StrictCindyKnown/StrictCindy(cindy-provider 身份随认证快照透传)。L135-L144 关于 ProfitControl 字段“漏投影则门静默失效”的注释在利润控制运行期退役后已过时但无害(字段保留、值恒 false/0)。核心认证快照机制。静态阅读,未执行构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "APIKeyAuthGroupSnapshot L59-L145 adds StrictCindyKnown/StrictCindy L65-L66; ProfitControl* fields retained L142-L144 with now-stale comment L135-L141", - "Consumed by api_key_auth_cache_impl.go snapshotFromAPIKey/snapshotToAPIKey", - "File statically reviewed only; no build run." - ] - }, - { - "path": "backend/internal/service/api_key_auth_cache_impl.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "879a16bb9c0e86246b06747baf728f2c920463825cd64980b175d021b659da56", - "review_fingerprint": "879a16bb9c0e86246b06747baf728f2c920463825cd64980b175d021b659da56", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "API Key 认证缓存实现(L1 ristretto + L2 Redis、快照序列化、跨实例失效 Pub/Sub、有界回源并发、负缓存)。下游相对上游把快照版本 24→26(退役 managed public routes 后重载旧快照)、from/to 快照透传 StrictCindy 身份、并把 ProfitControl 三字段在两方向恒置 false/0(与 profitControlRuntimeEnabled=false 的利润控制运行期退役一致,门恒不安装故非缺陷)。核心认证缓存机制。静态阅读,未执行测试/构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "apiKeyAuthSnapshotVersion=26 L17; snapshotFromAPIKey L334-L443 & snapshotToAPIKey L445-L548 add StrictCindy (L387-L388,L491-L492) and force ProfitControl false/0 (L437-L439,L541-L543)", - "Retirement confirmed: openai_profit_control.go:74-77 profitControlRuntimeEnabled=false; gateway_profit_control.go:14 installs no gate so veto is a no-op", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/api_key_auth_cache_profit_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "132bd21f64b508c1db52ee15f20d31a5739a4702a5655f7a8c897706be931729", - "review_fingerprint": "132bd21f64b508c1db52ee15f20d31a5739a4702a5655f7a8c897706be931729", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "认证快照利润字段测试。下游相对上游把原“利润字段全程保真并装门”的往返测试改写为“休眠零值”测试:输入分组 ProfitControlEnabled=true/0.2/0.05,经 snapshotFromAPIKey→JSON→applyAuthCacheEntry 后断言恒为 false/0/0 且 RateMultiplier 保真,并删除了对 resolveOpenAIProfitControlGate 装门的断言;另保留旧版本(v16)快照必须淘汰回源的断言。证明下游利润控制运行期退役后核心认证缓存的行为。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "profitAuthTestAPIKey L14-L42 feeds ProfitControlEnabled=true/0.2/0.05; TestAPIKeyAuthSnapshotDormantProfitControlRoundtrip L44-L68 asserts False/Zero/Zero after JSON roundtrip; TestAPIKeyAuthSnapshotOldVersionEvicted L71-L81", - "Diff removed ctxkey import and gate-threshold assertion (0.06*(1-0.25)); consistent with api_key_auth_cache_impl.go forcing ProfitControl false/0", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/api_key_auth_cache_version_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "657cd64872eab902485565b22941a2bd13c184288314575bdb3d1ba04a0f1f5a", - "review_fingerprint": "657cd64872eab902485565b22941a2bd13c184288314575bdb3d1ba04a0f1f5a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "认证快照版本兼容测试。下游相对上游新增两例:持久化的 v24 旧快照(含 models_list_config 旧字段名与 cindy 身份)必须 cache miss 而非以零值白名单命中;ModelAllowlist(启用/启用空/禁用保留条目)与 Cindy 身份(StrictCindyKnown/StrictCindy)及 ForceOpenAIFast 经 JSON 往返后保真且 Allows 语义不变。既有 v10/v15 拒绝用例保留。证明核心认证缓存版本门与下游字段透传。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestAPIKeyService_RejectsV24AuthSnapshotWithoutModelAllowlist L9-L24 (legacy JSON literal, expects miss); TestAPIKeyAuthSnapshotGroupModelAllowlistRoundtrip L26-L73 (3 allowlist configs, asserts DeepEqual + Allows + Cindy/Fast fields)", - "Pre-existing RejectsV10 L75-L113 and RejectsV15 L115-L131 unchanged; ties to apiKeyAuthSnapshotVersion=26 in api_key_auth_cache_impl.go:17", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/api_key_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ec29469b39bc584351c681f3acd857843b66ca59aab4954783099cbd27822137", - "review_fingerprint": "ec29469b39bc584351c681f3acd857843b66ca59aab4954783099cbd27822137", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主 API Key 服务(创建/更新/删除、认证读取热路径 GetByKey 经二级缓存+singleflight、配额与限流用量、IP 规则编译、分组绑定权限、防抖 last_used)。下游相对上游仅新增 ListAll(经 apiKeyAllByUserIDLister.ListAllByUserID 返回某用户全部 Key,供不可截断的管理面聚合)。核心 API Key 服务机制。静态阅读,未执行测试/构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "ListAll L579-L596 (unpaginated, requires apiKeyAllByUserIDLister); GetByKey auth hot path L722-L775; field-scoped Update L777-L933", - "Delta = ListAll only per git diff; no plugin-side duplicate", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/auth_service_platform_quota_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cec08ad1dc0a068c6af1274b918c6ac140ce5c1ff26485a125cbfd784f98006b", - "review_fingerprint": "cec08ad1dc0a068c6af1274b918c6ac140ce5c1ff26485a125cbfd784f98006b", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "核心 AuthService 注册时平台配额快照测试(unit tag):仅配置了限额的平台建行、全无限额不调 BulkInsertInitial、快照脱离调用方事务(best-effort 不毒化注册事务)、repo 错误 fail-open、nil plan/repo no-op、全局配额在 auth source 之前加载。下游相对上游唯一改动是 L211 在 t.Fatal 后补一个 return(nilness lint),不改变任何断言,故按静态参考材料归档。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestSnapshotPlatformQuotaDefaults_* L58-L188 incl. DetachesCallerTransaction L128-L152 asserting dbent.TxFromContext(lastCtx)==nil; TestResolveSignupGrantPlan_* L192-L236", - "git diff vs aea725f = single `return` after t.Fatal at L211; test substance identical to upstream", - "Test source read statically, not executed; does not prove a downstream fix." - ] - }, - { - "path": "backend/internal/service/billing_cache_service_user_platform_quota_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e0b02d85797982f881899602490fc43f0248bc4b5116ac37d67b53b5ca40a022", - "review_fingerprint": "e0b02d85797982f881899602490fc43f0248bc4b5116ac37d67b53b5ca40a022", - "review_status": "reviewed", - "decision": "upstream-covered", - "owner": "core-quota-and-protocol", - "reason": "BillingCacheService 的用户×平台配额单元测试(//go:build unit):用 fakeIncrCache/fakeQuotaRepo/fakeFullCache/fakeZeroQuotaCache 断言 IncrementUserPlatformQuotaUsage 同步直写并按 userID+platform 计费、空平台/零或负成本被忽略,checkUserPlatformQuotaEligibility 的日/周/月窗口过期归零并用 SetCache 刷新而非 Delete、旧 schema 回退 DB、无行时回填三 limit 全 nil 的 sentinel(TTL 取 UserPlatformQuotaSentinelTTLSeconds、Redis GET/SET 故障 fail-open、sentinel 跨窗口不刷新)、订阅模式 CheckBillingEligibility 不查平台配额、monthlyQuotaWindowExpired/nextMonthlyResetFrom 的 30 天滚动边界,以及 HasUserPlatformQuotaLimit 的 fail-safe 与 simple 模式。被测 billing_cache_service.go 与上游 aea725f 完全相同,本测试相对上游只在两处 t.Fatal 后加了不可达的 return(L377、L691),无任何下游行为差异。静态阅读,未执行断言。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S21-svc-gateway-billing-1-review.json", - "Test inventory: L37-L59 sync IncrUserPlatformQuotaUsageCache with userID/platform/cost/ttl/markDirty=false; L230-L391 eligibility (under limit, exhausted, nil=unlimited, zero=block, no record, old schema→DB, expired window in cache → refresh keeps limit and advances window_start); L397-L473 monthly rolling 30d helpers; L475-L491 empty/zero/negative guards; L546-L616 standard vs subscription bypass; L626-L671 boundary table; L676-L766 sentinel backfill/fail-open/no-refresh; L770-L834 HasUserPlatformQuotaLimit table.", - "git diff aea725f: +2 lines only — `return` after t.Fatal at L377 and L691 (unreachable, lint-only); subject file billing_cache_service.go has an empty diff vs aea725f (functions at billing_cache_service.go:709/1080/1349), so the proven behavior is upstream behavior.", - "Identity binding: every assertion passes explicit userID (1, 42, 99, 101) and platform into the service and checks the fake received the same tuple; the subscription bypass test uses user.ID=42 with group 10. Statically reviewed only; no test execution, nothing claimed about pass/fail." - ] - }, - { - "path": "backend/internal/service/billing_context_schedule.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "be7713d92aff47305812609d9de948307ac6563bb740e7b4755025208d7194ed", - "review_fingerprint": "be7713d92aff47305812609d9de948307ac6563bb740e7b4755025208d7194ed", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "为模型广场/价格展示解析分组+模型的上下文阶梯单价表:用与扣费同源的 Resolver.Resolve 与 CalculateTokenCostForRequest 做两点差商探针(每段只喂一种 token,倍率固定 1),断点仅来自渠道区间边界或目录 LongContextInputThreshold,相邻同价段合并并打 ≤/>/ `return s.CalculateCostUnified(...)`; with Resolver nil CalculateCostUnified (billing_service.go L1263-L1282) now honors input.PricingAt and applies maxReasoningEffortBillingMultiplier, which the old CalculateCost path skipped.", - "Callers (rg, non-test): gateway_usage_billing.go:1116 and billing_context_schedule.go:122 only. Finding recorded: dead conditional branches L31-L39 (low). No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/business_system_prompt_account_scope_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8a7ea36296ad2b688951311a39623da8bc9cd4728cf2e76a7eb00d832e9c8e82", - "review_fingerprint": "8a7ea36296ad2b688951311a39623da8bc9cd4728cf2e76a7eb00d832e9c8e82", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_bundle.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "c4653a508fc53b2786b4497ce55e7dd7c3a5df8faab79e099c5fe16923eda3f1", - "review_fingerprint": "c4653a508fc53b2786b4497ce55e7dd7c3a5df8faab79e099c5fe16923eda3f1", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_bundle_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "91fb3bc38cf42f79b6e73fbd9cf77ba7f7c0beba96e722c2b15f327287d07022", - "review_fingerprint": "91fb3bc38cf42f79b6e73fbd9cf77ba7f7c0beba96e722c2b15f327287d07022", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_cache_identity_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b4a5759a54bad6a1d09b9f78734853875df9d48fe3bf83458e60bdb042dc6864", - "review_fingerprint": "b4a5759a54bad6a1d09b9f78734853875df9d48fe3bf83458e60bdb042dc6864", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_composition.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "cd93c0e64507e99434d43bcea6db9a0c0f2c73e07716a01846b9bffce96c1da0", - "review_fingerprint": "cd93c0e64507e99434d43bcea6db9a0c0f2c73e07716a01846b9bffce96c1da0", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_composition_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fba4437a7215398ce4bd34c4c1cb165b71e358e3a9f72856fa3b3ccff03e093d", - "review_fingerprint": "fba4437a7215398ce4bd34c4c1cb165b71e358e3a9f72856fa3b3ccff03e093d", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_gateway_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d22cc0a9608d1adda89f11ec2cf676b3e36b0dc82fb50f7e5cee585da08ee31f", - "review_fingerprint": "d22cc0a9608d1adda89f11ec2cf676b3e36b0dc82fb50f7e5cee585da08ee31f", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_offline_integration_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c339c3c1e0a10c88bd03dc748bf9566c2630f57cc0cbc7cf58b579ad735d16cd", - "review_fingerprint": "c339c3c1e0a10c88bd03dc748bf9566c2630f57cc0cbc7cf58b579ad735d16cd", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_policy.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "ae70b538f043c074e6c9647b985b64335a939c745cfbda12c9c27f9a8ba726b2", - "review_fingerprint": "ae70b538f043c074e6c9647b985b64335a939c745cfbda12c9c27f9a8ba726b2", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Full source read. The bounded plan request carries the trusted target AccountID in Invocation as well as Target. Planning is separated from local body application so cache hits can re-enter execution admission without sending customer content or applying a second insertion. Existing input validation and JSON/SSE response rewriting remain unchanged.", - "evidence": [ - "artifacts/evidence/v027-astra-prompt-request-scope-review.json: exact phased failures, targeted RUN/PASS, carrier provenance and full-versus-partial file scope" - ] - }, - { - "path": "backend/internal/service/business_system_prompt_service.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "a12674b9d4cdb4e30b9afcd45f9b09dd3036bf9b7fd9ca4815b3d58b5516b016", - "review_fingerprint": "a12674b9d4cdb4e30b9afcd45f9b09dd3036bf9b7fd9ca4815b3d58b5516b016", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_service_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d3ac37dab84c5384b87f2b4e62369deb79f6bb34c2427780a36736423b2b4738", - "review_fingerprint": "d3ac37dab84c5384b87f2b4e62369deb79f6bb34c2427780a36736423b2b4738", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9b05bf2473e6c842cf16c8b07af2d2b83482790993224122bf6f175a26d1a7c5", - "review_fingerprint": "9b05bf2473e6c842cf16c8b07af2d2b83482790993224122bf6f175a26d1a7c5", - "review_status": "pending" - }, - { - "path": "backend/internal/service/business_system_prompt_turn_cache.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "f9bd3ebc8a363f7537cc49765e7e54efbf72b28b4c79a528bc6dc57ffc8ac8bf", - "review_fingerprint": "f9bd3ebc8a363f7537cc49765e7e54efbf72b28b4c79a528bc6dc57ffc8ac8bf", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Fully read new host-only cache mechanism. A mutex protects the current turn map; one stable Gin key owns it and pointer replacement releases completed-turn snapshots/body values. HTTP requests retain their existing Gin storage. Nil contexts do not read or write. No arbitrary deletion or unrelated session mutation.", - "evidence": [ - "artifacts/evidence/v027-prompt-turn-cache-review.json: E-WS-SOURCE, E-WS-RED, E-WS-GREEN and E-WS-DIRECT-CONTROLS", - "Targeted passing selectors are bound to the unchanged production delta." - ] - }, - { - "path": "backend/internal/service/business_system_prompt_turn_cache_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6414a46693bbd947e9b058dbc48b42bc8feaf751db78c3b1edbee3bcfc173334", - "review_fingerprint": "6414a46693bbd947e9b058dbc48b42bc8feaf751db78c3b1edbee3bcfc173334", - "review_status": "pending" - }, - { - "path": "backend/internal/service/channel_cindy_managed_crud_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "61d965d125d928e4921091ce8e5cb30cf5656666e847a34537f46bd4d5475812", - "review_fingerprint": "61d965d125d928e4921091ce8e5cb30cf5656666e847a34537f46bd4d5475812", - "review_status": "pending" - }, - { - "path": "backend/internal/service/channel_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9af7feec26c8037bc233f64e8a7a05bce914462ef5497b8b53bd96599b951f45", - "review_fingerprint": "9af7feec26c8037bc233f64e8a7a05bce914462ef5497b8b53bd96599b951f45", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "渠道服务:渠道缓存快照(按 groupID+platform+model 的定价/映射哈希、通配符、singleflight 重建、Redis 失效广播)、热路径定价/映射/模型限制查找、定价配置校验(冲突、区间、计费模式、分时)以及 Create/Update/Delete/List CRUD。下游相对上游 aea725f 新增 38 行 Cindy 托管目录渠道的宿主适配:populateChannelCache 时 hydrateManagedCindyCatalogChannel 把插件目录投影成该渠道的 ModelMapping 并清空定价;checkRestricted 对托管渠道改用 cindyManagedChannelModelAllowed;Create/Update 拒绝保留名 \"Cindy Catalog\"、features_config 里的托管标记,以及把 Cindy 分组绑到普通渠道(rejectCindyGroupsOnOrdinaryChannel),错误码 MANAGED_CINDY_CHANNEL_IMMUTABLE。这些判定全部经 cindy_channel_catalog.go → queryCindyCatalog 转到 Cindy 目录(plugins/cindy-provider/catalog/channel.go 的 managedChannelProjection/managedChannelModelAllowed),核心不保留第二份模型白名单,属于核心渠道机制加插件适配。缺口:Delete(L1048-L1062)与 admin handler 均未套用托管渠道不可变守卫,且该渠道仅由迁移 236 创建、无运行时重建(见 findings)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S21-svc-gateway-billing-1-review.json", - "Read L1-L1210: L96-L108 channelCache maps keyed by (groupID, platform, model) bounded by configured channels; L191-L215 loadCache with 10m TTL + singleflight; L292-L304 buildCache uses context.WithoutCancel + 10s DB timeout; L336-L356 populateChannelCache (L343 hydrate hook); L632-L645 checkRestricted (L636-L638 managed branch); L826-L879 Create (L827-L832 guards); L893-L933 Update (L898-L905 guards); L935-L949 rejectCindyGroupsOnOrdinaryChannel by group.Platform==cindy or ProviderProfileCindyLaxaV1; L1048-L1062 Delete has no managed-channel guard.", - "git diff aea725f (+38): ErrManagedCindyChannelImmutable L26-L29, hydrate call L343, managed restrict L636-L638, Create/Update guards, rejectCindyGroupsOnOrdinaryChannel. Helpers live in cindy_channel_catalog.go L16-L63 and query the catalog via queryCindyCatalog (cindy_capability_catalog.go:60) with methods ManagedChannelProjection / ManagedChannelModelAllowed, implemented by plugins/cindy-provider/catalog/channel.go L10-L35 — one source of truth, no duplicated executor in core.", - "Creator trace: only backend/migrations/236_bind_strict_cindy_groups_to_catalog_channel.sql inserts the channel (name 'Cindy Catalog', features_config {\"cindy_catalog_managed\":\"cindy_laxa_v1\"}); rg over backend/plugins non-test Go for the marker constants finds no runtime creator; handler/admin/channel_handler.go:582-589 Delete calls channelService.Delete without a guard. Finding recorded (medium).", - "Not claimed: request-time behavior after a deletion was not exercised; static reading only, no test execution, no production behavior edit." - ] - }, - { - "path": "backend/internal/service/cindy_account_test_plan.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "24517d0df792f0c9c0f25f887a402b632c01c5e68a5862845bface628cc9f496", - "review_fingerprint": "24517d0df792f0c9c0f25f887a402b632c01c5e68a5862845bface628cc9f496", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_account_view_probe_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "37354a116ece731addd32f00088bfa04727794909c3f08ee7337738eab2f8079", - "review_fingerprint": "37354a116ece731addd32f00088bfa04727794909c3f08ee7337738eab2f8079", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "`//go:build unit` 测试(185 行,下游新增,上游无此文件),验证 Cindy 余额探测任务与插件 AccountView 视图绑定的宿主桥接:视图裁剪先于候选计数(rollout 50% 时 preview 只剩 AccountID=2)、origin 编解码保留 OperationKey/FrozenAccountIDs、BindCindyBalanceProbeOrigin 在绑定禁用或 origin 畸形时拒绝而不降级为旧式任务、显式 selected 越界账号拒绝整个 preview、all/filter 探测保留 Provider100 门禁、finalizeExhausted 只走 FinalizeScopedExhausted 并要求已提交 episode 才投影且不产生无作用域的 pending 重试、origin JSON 不泄露搜索词/凭据、Rebind 只在同定义(同 RequestDigest、同包 SHA、未收窄视图)下重新接纳并不原地改写已保存 origin。被测对象是宿主侧 cindy_balance_probe_service.go/plugin_account_views.go 的桥接代码,不含 Cindy 业务规则,归 adapter/cindy-provider。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L16-L54 TestAccountViewProbeScopeBeforeCountingAndFrozenOrigin: BindAccountViewRequest -> BindResourceContext -> captureCindyProbeOrigin -> BuildCindyBalanceProbePreviewFromSnapshotContext asserts CandidateCount==1 / AccountID==2 under RolloutPercent=50; Encode/DecodeCindyBalanceProbeScope roundtrip; BindCindyBalanceProbeOrigin errors on disabled binding and on `{\"origin\":\"malformed\"}` (Origin must stay non-nil).", - "L56-L72 explicit `selected` scope with out-of-view account IDs {2,5} rejected; all/filter probe still fails when binding rollout is narrowed to 50 (Provider100 gate). L74-L124 finalizeExhausted uses scopedProbeTerminalFixture: scopedCalls==1, legacyCalls==0, ApplyCommittedProbeTerminal projected once, ObserveCindyHealthSignal never called; repo error and nil committed episode both return false without a new projection.", - "L126-L142 origin JSON must not contain the view search string, `credentials` or `synthetic-private-key`; L144-L185 RebindCindyBalanceProbeOrigin adopts RuntimeGeneration+1 with same RequestDigest/FrozenAccountIDs, refuses narrowed rollout and changed PackageSHA256, and leaves the stored origin bytes unchanged.", - "Subjects located with rg: captureCindyProbeOrigin/BindCindyBalanceProbeOrigin/RebindCindyBalanceProbeOrigin/finalizeExhausted in cindy_balance_probe_service.go L545-L665; BuildCindyBalanceProbePreviewFromSnapshotContext/Encode/Decode in cindy_balance_probe_types.go L340-L424; fixtures newViewFixture/applyViewFixture in plugin_account_views_test.go L133-L163. Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/cindy_alpha_search_plan.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "573e96df9f1db3c07c81f5519543694273e1ed16c1bddc190884242125a51f5e", - "review_fingerprint": "573e96df9f1db3c07c81f5519543694273e1ed16c1bddc190884242125a51f5e", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_alpha_search_plan_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e7e95400a77bb58dcfbd677b26b1ed85dd0155f08906be005f5556be02e7878c", - "review_fingerprint": "e7e95400a77bb58dcfbd677b26b1ed85dd0155f08906be005f5556be02e7878c", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "The fixture captures each RPC so assertions check both plan and catalog receive the real account ID with only model metadata. Tests reject mismatched catalog model/owner and extra JSON before the second query; construction assertions preserve the native Messages max_uses while keeping that non-native field out of Responses. This is a synthetic contract test, not upstream quality evidence.", - "evidence": [ - "TestResolveCindyAlphaSearchPlanSendsOnlyRequestedModel checks the exact JSON payload, both scoped invocations and returned plan.", - "TestCindyAlphaSearchPlanCannotChangeCatalogIdentityOrReturnTrailingJSON uses distinct model/owner/extra-document cases with an error assertion and confirms malformed data stops before catalog IO.", - "TestValidateCindyAlphaSearchPlanRejectsUnboundedOrUnexpectedFallback and TestCindyAlphaSearchBodiesUseProviderPlanFields are unchanged direct assertions; their previously passed results were not rerun." - ] - }, - { - "path": "backend/internal/service/cindy_balance.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "1221908442da4259974a8f910bc2965acc217c57bec959122f60b12c6ec35ca1", - "review_fingerprint": "1221908442da4259974a8f910bc2965acc217c57bec959122f60b12c6ec35ca1", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "Cindy 余额不足信号的宿主侧适配层(316 行,下游新增):定义 CindyBalanceSignal 枚举、余额/封禁清理与 pending 标记的仓储接口、请求级 cindyBalancePendingSnapshot(只对严格 Cindy 账号按 AccountID 记录 clear/blocked/readFailed,避免同一请求重复读旧 Redis 标记)、把余额终态事件包装成不可同账号重试的 UpstreamFailoverError(HTTP 分支要求恰好 200 才承认带内事件),以及 cindy-insufficient:v1 / cindy-account-identity:v2 两个域分隔的 SHA-256 指纹。真正的 budget_exceeded+429 判定规则不在此文件:ClassifyCindyBalanceInsufficient 先用 IsCindyAPIKeyAccount 门禁,再经 plugin_cindy.go classifyCindyProviderResponse 以 cindy.health 调用 cindy-provider 插件(plugins/cindy-provider/catalog/health.go Registry.ClassifyResponse)并携带真实 account.ID,因此核心只是薄适配而非第二执行器。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L15-L91 error values, CindyInsufficientDeletePreview/Result DTOs, repository interfaces (CindyBannedAccountRepository, CindyHealthStateCleaner, CindyHealthTerminalPendingManager, CindyBalanceRuntimeClearer, CindyBalanceAccountRepository, CindyBalancePendingStore); L54-L61 CindyBalanceSignal None/HTTP429/ResponseFailed/ErrorEvent matches plugin Balance codes 1/2/3.", - "L93-L181 request-scoped cindyBalancePendingSnapshot (sync.RWMutex, map[int64]state) installed by ensureCindyBalancePendingSnapshotContext; callers openai_account_runtime_block_fastpath.go L1026/L1059 and openai_account_scheduler.go L2354 — per-request, not process-global, so it cannot grow unbounded.", - "L183-L258 IsCindyBalanceInsufficientResponse -> ClassifyCindyBalanceInsufficient -> classifyCindyProviderResponse (plugin_cindy.go L23-L44: gjson extracts type/error.type/error.code/response.error.*, invokes extension Capability provider / Operation cindy.health with AccountID=account.ID); the budget_exceeded && code 429 rule exists only in plugins/cindy-provider/catalog/health.go L17-L34. newCindyBalanceTerminalFailover uses generic openAITransportFailoverBody, RetryableOnSameAccount=false, CindyBalanceInsufficient=true; cindyBalanceHTTPResponseTerminalFailover/handleCindyBalanceHTTPResponseTerminalEvent gate on statusCode==200.", - "L261-L316 CindyInsufficientAccountFingerprint (cindy-insufficient:v1 over account IDs) and CindyAccountIdentityFingerprint (cindy-account-identity:v2 over platform/type/full credentials JSON) consumed by repository/account_repo_cindy_balance.go L99/L220-L258 and cindy_balance_probe_repo.go L614/L989 for identity-bound clears; NormalizeCindyCredentialsFingerprint accepts only 64-hex. rg found no identity/fingerprint duplicate under plugins/cindy-provider. Not claimed: runtime behavior of the gateway callers (23 call sites listed via rg) was not exercised." - ] - }, - { - "path": "backend/internal/service/cindy_balance_native_messages_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fb275ccbd4e7b68063bdd108906e77b69203119c06f190dba903cc03a010c8e8", - "review_fingerprint": "fb275ccbd4e7b68063bdd108906e77b69203119c06f190dba903cc03a010c8e8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "`//go:build unit` 测试(336 行,下游新增),验证宿主网关在 Anthropic 原生 /v1/messages 直通与 HTTP→WS 桥接两条传输链路上对 Cindy 余额终态信号的处理:200+SSE error 事件在未写回前触发不可同账号重试的 failover 且 ResponseBody 不透出 budget_exceeded;已输出语义内容后仍 failover 但丢弃原始 payload 与敏感文本;精确 429 预算耗尽不进入 pool_mode 重试循环、首个精确信号只投递 CindyHealthSignalExactBudget 而不持久化 CindyBalanceInsufficientAt;403 走共享 Forbidden 瞬时健康信号;首个 message_start 前置事件与本地 keepalive ping 在分类前被缓冲;子进程用 GATEWAY_CINDY_BALANCE_DETECTION_ENABLED=false 验证特性回滚后前置事件立即透传。被测对象是 GatewayService.ForwardCindyAnthropicMessages / handleStreamingResponseAnthropicAPIKeyPassthrough 与 OpenAIGatewayService.proxyOpenAIWSHTTPBridgeTurn 这些核心传输机制;预算判定规则本身由 cindy-provider 插件经 cindy.health 提供,插件目录下无 Anthropic 原生传输逻辑。仅静态阅读,未执行测试(含 exec.Command 子进程用例)。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L24-L58 HTTP200 SSE `event: error` budget_exceeded/429 -> UpstreamFailoverError{CindyBalanceInsufficient:true, RetryableOnSameAccount:false}, repo.markCalls==0, account.CindyBalanceInsufficientAt nil, c.Writer not written, health.signals==[ExactBudget]; L60-L104 after content_block_delta output: Writer.Written()==true, body contains `\"text\":\"ok\"` but not budget_exceeded / 'sensitive upstream detail'.", - "L106-L143 exact 429 with pool_mode retry_count=3 and retry status 429: upstream.calls==1, runtimeBlocker.isOpenAIAccountRuntimeBlocked false, health.accounts==[account.ID]; L145-L177 403 -> StatusCode 403, repo.setErrorCalls==0, signals==[Forbidden]; L179-L215 200 application/json error body fails over before write.", - "L217-L256 io.Pipe stream with StreamKeepaliveInterval=1 and 1200ms gap: recorder body stays empty until exact balance event (preamble + ping replay-safe); L258-L336 TestCindyBalanceRollbackPreservesImmediateTransportPreambles re-execs the test binary with CindyBalanceDetectionEnabledEnv=false and helper env; subtests assert message_start is forwarded (native Messages) and response.created reaches the WS writer via proxyOpenAIWSHTTPBridgeTurn.", - "Subjects located with rg: gateway_anthropic_passthrough.go L54 ForwardCindyAnthropicMessages, L478 handleStreamingResponseAnthropicAPIKeyPassthrough; openai_ws_http_bridge.go L451 proxyOpenAIWSHTTPBridgeTurn; gateway_service.go L861 SetCindyHealthCoordinator. Fixtures: cindy_balance_shared_test.go (exactCindyBudgetExceededBody, cindyRateLimitAccountRepoStub, cindyHealthCoordinatorRecorder), cindy_native_messages_test.go L17/L35, gateway_anthropic_apikey_passthrough_test.go L24, cindy_feature_flags_test.go L374. rg -i anthropic|messages under plugins/cindy-provider hits only catalog data/search, no transport code. Not executed; no claim about real upstream behavior." - ] - }, - { - "path": "backend/internal/service/cindy_balance_pending_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9b3af6a24dcb7233b7dc55ced0350087af30c51701ead6a2e00988e8f00ed37d", - "review_fingerprint": "9b3af6a24dcb7233b7dc55ced0350087af30c51701ead6a2e00988e8f00ed37d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "`//go:build unit` 测试(240 行,下游新增),用 cindyBalancePendingStoreStub 验证 OpenAIGatewayService 运行时拦截对 v0.1.177 之前遗留 Redis pending 标记的处理只剩清理语义:无数据库标记时遗留标记不阻塞调度且按身份指纹匹配清理(清理失败仍可调度);Redis 批量/指纹读失败时只信任 CindyBalanceInsufficientAt 数据库标记,且已有 DB 标记的账号不再查询 Redis;凭据轮换后旧指纹的 pending 不阻塞当前密钥;withCindyBalancePendingSnapshot 对 2000 个账号只做一次批量 HasCindyBalancePendingBatch;管理员 ClearCindyBalanceInsufficient 在遗留清理失败时仍成功解除运行时拦截。被测对象是核心调度/运行时拦截与管理员恢复路径(openai_account_runtime_block_fastpath.go、admin_cindy_balance.go),属宿主机制;身份指纹来自 cindy_balance.go 的 CindyAccountIdentityFingerprint,绑定真实账号凭据而非仅 ID。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L15-L98 cindyBalancePendingStoreStub embeds *stubGatewayCache (openai_gateway_service_test.go L739) and implements CindyBalancePendingStore with call counters and injectable hasErr/getErr/clearErr; ClearCindyBalancePendingIfFingerprintMatches deletes only when the stored fingerprint equals the supplied one.", - "L100-L129 TestCindyBalancePendingWithoutDatabaseMarkerIsCleanupOnly: legacy pending + matching CindyAccountIdentityFingerprint -> isOpenAIAccountRequestRuntimeBlocked false, hasCalls/getCalls/clearCalls==1, pending remains only when clearErr!=nil; L131-L162 batch read error -> unmarked account not blocked, account with CindyBalanceInsufficientAt blocked and hasCalls stays 1; fingerprint read error -> not blocked, pending retained.", - "L164-L178 rotated api_key: old-fingerprint pending cleared by isCindyBalancePendingBlocked and does not block; L180-L199 2000 accounts through withCindyBalancePendingSnapshot -> hasCalls==1, lastBatch==2000, account 777 cleared; L201-L240 adminServiceImpl.ClearCindyBalanceInsufficient after BlockCindyHealthEpisode: updated.CindyBalanceInsufficientAt nil, runtime unblocked, legacyClearCalls==1 regardless of legacy clear error.", - "Subjects located with rg: openai_account_runtime_block_fastpath.go L794 BlockCindyHealthEpisode, L1025 withCindyBalancePendingSnapshot, L1049 isCindyBalancePendingBlocked, L1570/L1574 isOpenAIAccountRequestRuntimeBlocked(Context); admin_cindy_balance.go L17 ClearCindyBalanceInsufficient. Fixtures: cindy_balance_shared_test.go L35/L179, cindy_identity_test.go L10, cindy_health_service_test.go L207, admin_cindy_balance_test.go L14, admin_service_clear_error_test.go L13. Test read statically; not executed." - ] - }, - { - "path": "backend/internal/service/cindy_balance_probe_service.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "f71a6f6e249780baf66d99f5ff3f5c1af2d29417e25c9de7f07bf777bf073fd3", - "review_fingerprint": "f71a6f6e249780baf66d99f5ff3f5c1af2d29417e25c9de7f07bf777bf073fd3", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "管理员显式创建的 Cindy 余额探测任务的宿主执行器(当前 774 行,下游新增;审阅期间协调者提交 d562e7179 使 Resume 在读取任务前先做探测策略失败关闭检查,文件 sha 已与切片不一致)。它只提供通用任务机制:uuid 租约 ClaimJob/Heartbeat(丢租约即 cancel 并停止)、RecoverInterruptedItems、ReserveNext/CompleteStage/FinishIfDone 循环、wake 通道与 Stop 时等待 goroutine 退出;所有 Cindy 业务规则都经 plugin_cindy_probe.go 以 cindy.probe.plan / cindy.probe.decide 调用 cindy-provider 插件(plugins/cindy-provider/catalog/probe.go balanceProbePlan/decideBalanceProbe 决定探测模型、luna/terra 阶段与 recover/exhausted/complete 动作),核心只对返回的计划做边界校验并执行动作,不存在第二执行器。账号身份绑定使用真实 AccountID:每次预约都按 reservation.AccountID 重新加载账号并经 CindyBalanceProbeReservationMatchesAccount 比对,作用域任务再验证 FrozenAccountIDs/ValidateAccountViewTargets/ValidateResourceAccounts,插件上下文以 AccountID=account.ID 重新绑定,exhausted 终态要求 committed.AccountID==reservation.AccountID 且按 IdentityFingerprint 清理遗留 pending。captureCindyProbeOrigin 拒绝来自 HTTP/插件的 Origin 副本,用视图身份+查询摘要+包 SHA+费率+期望计数生成 RequestDigest;bindCindyBalanceProbeOrigin 校验版本/插件键/包 SHA/代数并在显式恢复时重新校验冻结目标。未发现阻塞缺陷;仅静态阅读,未执行。 协调者补记:代理已全文阅读 d562e7179(Resume 先做策略检查)后的 774 行版本并确认无缺陷,记录按该版本 SHA 绑定。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L21-L67 CindyBalanceProbeService struct/Start/Stop (startOnce/stopOnce, cancel + wg.Wait); L69-L129 Preview/CreateJob gate on requireCindyBalanceProbePolicy (plugin_cindy_probe.go L14 -> cindy.probe.plan; disabled -> 404 CINDY_BALANCE_PROBE_DISABLED, other -> 503), canonicalize scope, captureCindyProbeOrigin(expectedCount, fingerprint) before repo.CreateJob.", - "L156-L207 Resume: policy check before repo.GetJob (the d562e7179 fail-closed change), scoped jobs rebind via rebindCindyProbeOrigin then CindyScopedProbeResumeRepository.ResumeScoped(stored.Origin, next); L209-L227 Cancel of scoped job calls FinishIfDone with empty lease token under a 3s WithoutCancel context (host-only progress finalization; repository authority semantics not verified here).", - "L234-L262 run loop: cindyBalanceProbePlan(s.ctx) gate each poll, leaseToken=uuid.NewString(), ClaimJob(now+cindyBalanceProbeLeaseDuration 60s); L279-L361 processJob: origin-bound or process-extension-bound jobCtx, heartbeat goroutine every 10s closes lostLease+cancel on !ok, deferred cancel waits heartbeatDone, ReserveNext(now, now-5m confirmation window), FinishIfDone when no reservation.", - "L377-L446 executeReservation: scoped origin requires slices.Contains(origin.FrozenAccountIDs, reservation.AccountID) + ValidateAccountViewTargets + manager.ValidateResourceAccounts; loadReservationAccount -> accountRepo.GetByID + CindyBalanceProbeReservationMatchesAccount (cindy_balance_probe_types.go L187); ValidateReservationForSend; bindProcessExtensionContext(cindy.probe.plan, AccountID=account.ID) with ErrExtensionOperationDisabled -> completeStage stale/skipped_stale; plan from cindyBalanceProbePlanForAccount (bounds check L50-L61 of plugin_cindy_probe.go), stage terra -> Models[1]; probeCindyBalanceModel (cindy_balance_recheck.go L28) under 20s timeout.", - "L460-L480 completeReservation dispatches plugin decision.Action recover/exhausted/complete (plugins/cindy-provider/catalog/probe.go L16-L46 decideBalanceProbe owns the rule); L507-L548 finalizeRecovery captures terminal pending, FinalizeRecovery, clears legacy pending by reservation.IdentityFingerprint under detachPluginPolicyContext, ClearCindyHealthTerminalPendingIfMatch -> ClearCindyHealthEpisodeBlock; L550-L613 finalizeExhausted: scoped path requires CindyScopedProbeTerminalRepository and committed.terminalValid() && committed.AccountID==reservation.AccountID before ApplyCommittedProbeTerminal, legacy path ObserveCindyHealthSignal(ExactBudget).", - "L615-L662 captureCindyProbeOrigin: scope.Origin=nil first, ValidateAccountViewFresh, installation generation/state check, stampAccountJobView/AccountJobViewExecution snapshot, OperationKey regexp ^[a-zA-Z0-9:_-]{1,160}$, RequestDigest sha256 over scope+view identity+query digest+owner+package+rate+count+fingerprint; L664-L727 bindCindyBalanceProbeOrigin validates Version==1, PluginID, generations, 64-hex PackageSHA256/RequestDigest, non-empty positive FrozenAccountIDs, same view identity, BindResourceContext(grant cindy.probe.create/admin), PluginKey match, ValidateResourceAccounts; explicit resume re-validates frozen targets and adopts current generations into a copy (`next := *origin`). L729-L774 bindCindyProbeOrigin/rebindCindyProbeOrigin via processExtensionOperations invoker type assertion, CindyBalanceProbeOriginOwner, ValidateCindyBalanceProbeOriginContext.", - "Observation (not a finding): regexp.MustCompile in captureCindyProbeOrigin is recompiled per call; stage names luna/terra are a shared extensionapi contract used by both host (model index) and plugin (decision), not a duplicated rule. Statically reviewed only; no tests or builds executed.", - "sha256 mismatch at assembly: slice 890f697be55ebc9997b8ae701c7b2187a2ce94e5bdf1c70742829af3945c9ea2, live f71a6f6e249780baf66d99f5ff3f5c1af2d29417e25c9de7f07bf777bf073fd3; record describes the live bytes that were fully read, but the fingerprint is stale and the record is left pending for re-binding.", - "Coordinator rebind after agent read full current file: commit d562e7179, sha f71a6f6e2497" - ] - }, - { - "path": "backend/internal/service/cindy_balance_probe_service_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f2fad5d55953d7b72a58dfc904f57deb386b98d32036f7cbecde43855c9cefd2", - "review_fingerprint": "f2fad5d55953d7b72a58dfc904f57deb386b98d32036f7cbecde43855c9cefd2", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "CindyBalanceProbeService 宿主执行器的单元测试(713 行,下游新增,无 build tag),用桩仓储/缓存验证任务机制与身份绑定:finalizeExhausted 只在仓储事务返回 exhausted/already_marked 后才通过健康协调器安装 cindyHealthRuntimeBlocks 诊断阻断(数据库失败不阻断、ctx 已取消无副作用、绝不创建旧式指纹运行时阻断);finalizeRecovery 在 Redis 清理失败或被并发替换 episode(afterClear/afterGet 交错)时仍以数据库恢复为准且不误清新 episode,普通请求不得从陈旧缓存重新打标;已标记账号 luna 成功走 recover 并把发送前账号快照原样交给 FinalizeRecovery;run 每次 ClaimJob 使用不同 uuid 租约;ValidateReservationForSend 返回未就绪或账号 UpdatedAt 漂移时在探测前停止且不 CompleteStage(gateway=nil 时任何误探测会 panic);CindyBalanceProbeReservationMatchesAccount 对 ID/完整凭据对象/UpdatedAt 微秒/状态/可调度/非 Cindy base_url/标记代数漂移全部返回 false;CreateJob 将 selected 作用域去重排序并把 Filters.AccountIDs 提升为 AccountIDs 后原样传给仓储并透传 ErrCindyBalanceProbeChanged;旧版 JSON 解码/编码规范化与快照预览过滤。决策动作来自 cindy-provider 插件(测试进程经 TestMain 注入的进程内扩展),测试证明的是宿主桥接而非 Cindy 业务规则。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L13-L118 stubs: recovery/finalize/dispatch/claim-epoch/create repository stubs embedding CindyBalanceProbeRepository, cindyBalanceProbePendingStoreStub (pending map + terminalPending episode with exact-match CAS clear L225-L268), cindyBalanceProbeDiagnosticHealthCoordinator installs a CindyHealthEpisode via BlockCindyHealthEpisode using AccountCredentialFingerprint(ProviderProfileCindyLaxaV1, api.laxarouter.ai, api_key).", - "L270-L346 TestCindyBalanceProbeFinalizeExhaustedBlocksOnlyAfterDatabaseCommit: cases exhausted/already_marked -> wantBlock, clearCalls==1, health.seen==1, cindyHealthRuntimeBlocks holds 'diagnostic-episode'; database failure -> no block; canceled ctx -> return true, no side effects; beforeFinalize asserts openaiAccountRuntimeBlockUntil is still empty; cindyBalanceRuntimeBlockFingerprint never populated.", - "L348-L393 recovery with clearErr keeps store.pending evidence, isOpenAIAccountRuntimeBlocked false, markRepo.markCalls==0; L395-L439 replacement episode installed inside afterClear survives (block.Episode.EpisodeID==diagnostic-replacement); L441-L476 nil capture + afterGet install retains block; L478-L500 completeReservation(luna, WasMarked, cindyBalanceProbeSuccess) -> FinalizeRecovery once with require.Same(account, accountSnapshot).", - "L502-L529 run() with ClaimJob stub: two distinct non-empty claimTokens, worker stops within 1s; L531-L567 ready=false -> executeReservation false, validateCalls==1 with lease/item/JobRequestCount/account captured, completeCalls==0; L569-L620 CindyBalanceProbeReservationMatchesAccount matrix (8 cases); L622-L655 databaseUpdatedAt drift after GetByID -> stop before probe.", - "L657-L684 CreateJob canonical scope {Mode selected, AccountIDs [17,19], Filters{CindyOnly}} forwarded with rate 0.5/count 1/fingerprint, ErrCindyBalanceProbeChanged propagated; L686-L713 DecodeCindyBalanceProbeScope of legacy filters.account_ids -> AccountIDs [17,19], EncodeCindyBalanceProbeScope JSON shape, BuildCindyBalanceProbePreviewFromSnapshot keeps only account 17. Subjects: cindy_balance_probe_service.go (finalizeExhausted/finalizeRecovery/completeReservation/run/executeReservation) and cindy_balance_probe_types.go (matcher, scope codec, preview). Not executed." - ] - }, - { - "path": "backend/internal/service/cindy_balance_probe_types.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "1dfcb1b3756487dbd37429858dae4b015b6e13acd37e70133cd4948058a263d8", - "review_fingerprint": "1dfcb1b3756487dbd37429858dae4b015b6e13acd37e70133cd4948058a263d8", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "Cindy 余额探测任务的宿主侧类型与作用域/候选计算(479 行,下游新增):常量(费率 0.1–1.0、租约 60s、心跳 10s、探测超时 20s、确认窗口 5 分钟)、错误码、Scope/Origin/Preview/Job/Item/Reservation DTO、CindyBalanceProbeRepository 及作用域仓储可选端口、候选预览(只接受 Active+Schedulable 的严格 Cindy 账号,按完整凭据对象的身份指纹去重,候选指纹覆盖 ID|指纹|UpdatedAt 纳秒|是否已标记)、快照过滤复用管理台 AccountConsoleFilters/accountFacetMatcher、FromSnapshotContext 在绑定视图时先经 filterAccountViewAccounts 与视图查询过滤再做探测自身过滤且 selected 必须全部落在视图内、作用域 JSON 编解码(畸形 origin 不得降级为无作用域旧任务)、selected 账号 ID 规范化与唯一活动任务索引冲突映射。这些是宿主任务/视图机制与 DTO,不是 Cindy 判定规则;插件目录只持有探测计划与判定(probe.go),无候选/预览/作用域逻辑重复。Origin 仅由宿主盖章,预览由 repository/cindy_balance_probe_repo.go 在事务一致快照上调用。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L15-L49 rate bounds and lease/heartbeat/poll/timeout/confirmation constants, Conflict/NotFound/BadRequest errors (CINDY_BALANCE_PROBE_*); L51-L71 CindyBalanceProbeScope with host-stamped Origin (`json:\"origin,omitempty\"`, comment: HTTP DTO cannot supply it) and CindyBalanceProbeOrigin (Version, PluginID, PluginKey, PackageSHA256, RuntimeGeneration, View AccountJobViewMetadata, FrozenAccountIDs, OperationKey, RequestDigest).", - "L73-L182 Preview/Counts/Job/Item/Latest/Page/JobList/Reservation DTOs; LeaseToken/LeaseUntil and IdentityFingerprint/AccountUpdatedAt are `json:\"-\"` so admin responses do not expose lease or identity material. L184-L200 CindyBalanceProbeReservationMatchesAccount: same ID, Active, Schedulable, IsCindyAPIKeyAccount, UpdatedAt equal at microsecond precision, marker presence == WasMarked, CindyAccountIdentityFingerprint equality.", - "L202-L230 CindyBalanceProbeRepository (19 methods) + optional CindyScopedProbeTerminalRepository/CindyScopedProbeResumeRepository ports; L232-L278 BuildCindyBalanceProbePreview: filter strict active schedulable Cindy accounts, dedupe by ID, sort by AccountID, MinimumCalls=len, MaximumCalls=marked+2*unmarked, ETA=(calls-1)/rate.", - "L280-L334 BuildCindyBalanceProbePreviewFromSnapshot: selected mode copies AccountIDs into filters, applies search/account-id set/GroupID (ungrouped sentinel)/privacy_mode/facet matcher (admin_account_taxonomy.go L56/L1060/L1068) before building; L336-L385 FromSnapshotContext: filterAccountViewAccounts + AccountViewQueryFilters(view.Request.Query) intersection first, then probe scope, selected must pass ValidateAccountViewTargets and len(selected)==CandidateCount else ErrAccountViewScope. Sole non-test caller: repository/cindy_balance_probe_repo.go L180.", - "L396-L479 candidate fingerprint sha256 over `%d|%s|%d|%t`, ETA, rate validation, Encode/Decode (malformed JSON with non-null origin -> Origin=&CindyBalanceProbeOrigin{} so it cannot become a legacy job), CanonicalizeCindyBalanceProbeScope (lowercase mode; selected: fall back to legacy Filters.AccountIDs, drop <=0, dedupe, sort, clear Filters.AccountIDs), WrapCindyBalanceProbeCreateError maps idx_cindy_balance_probe_jobs_one_active / duplicate key to ErrCindyBalanceProbeActive. rg over plugins/cindy-provider finds no preview/scope/candidate duplication (only WasMarked in the decision rule). Not executed." - ] - }, - { - "path": "backend/internal/service/cindy_balance_recheck.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "e4ec755ffd46c88e3551372099c4335164d783671a9af46265faee2d6975e5cb", - "review_fingerprint": "e4ec755ffd46c88e3551372099c4335164d783671a9af46265faee2d6975e5cb", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "单次 Cindy 余额探测请求的宿主执行器(162 行,下游新增):probeCindyBalanceModel 以真实 account.ID 向 cindy-provider 插件取探测计划(模型必须是计划中的两个之一),用账号自己的 OpenAI base_url/api_key/代理/头覆盖发送非流式 Responses 请求,响应体限 64KiB(超限判 other),再把传输结果映射为 extensionapi 的 CindyProbeOutcome:预算耗尽判定交给 ClassifyCindyBalanceInsufficient(插件 cindy.health),SSE 要求恰好一个终态事件(response.failed/error 且为预算信号→exhausted;response.completed 且协议形状合法→success;冲突或重复终态→other),5xx→server failure,2xx 且 id/object=response/status=completed/output 非空/usage 数字齐全→success。成功形状校验是 OpenAI Responses 协议校验而非 Cindy 规则,SSE 解析复用上游已有的 forEachOpenAISSEDataPayload/extractOpenAISSETerminalEvent;插件侧无 HTTP 发送或形状校验,故不构成第二执行器。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L16-L26 cindyBalanceProbeMaxBodyBytes=64KiB, outcome type/constants aliased to extensionv1.CindyProbeOutcome (Other/Success/Exhausted/NetworkFailure/ServerFailure) so host and plugin share one enum.", - "L28-L92 probeCindyBalanceModel: guards nil/ID<=0/httpUpstream; cindyBalanceProbePlanForAccount(ctx, account.ID) and model membership check; body {model,input,max_output_tokens,stream:false}; buildOpenAIResponsesURL(account.GetOpenAIBaseURL()) (upstream helper, openai_gateway_request_body.go L52), Bearer GetOpenAIApiKey, ApplyHeaderOverrides, proxy from account.Proxy; httpUpstream.Do(req, proxyURL, account.ID, account.Concurrency); io.LimitReader(max+1) then len>max -> Other; classification order: plugin balance signal -> SSE -> >=500 -> 2xx success shape.", - "L94-L126 classifyCindyBalanceProbeSSE counts terminal events via forEachOpenAISSEDataPayload (openai_sse_data.go L35, present upstream): terminalCount!=1 -> Other; L128-L162 isValidCindyBalanceProbeSuccess (SSE terminal must be response.completed via extractOpenAISSETerminalEvent, openai_gateway_response_handling.go L2207, present upstream) and isValidCindyBalanceCompletedResponse (id, object==response, status==completed, output array non-empty, usage.input_tokens/output_tokens numbers).", - "Sole non-test caller: cindy_balance_probe_service.go L441 under a 20s timeout. Balance rule ownership: plugins/cindy-provider/catalog/health.go via ClassifyCindyBalanceInsufficient; probe plan ownership: plugins/cindy-provider/catalog/probe.go via plugin_cindy_probe.go. No network or execution performed during review." - ] - }, - { - "path": "backend/internal/service/cindy_balance_recheck_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1c07efd4cebf7b9071983665b0118d327b86255ee6833a9323bf17307ca12bcc", - "review_fingerprint": "1c07efd4cebf7b9071983665b0118d327b86255ee6833a9323bf17307ca12bcc", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "`//go:build unit` 测试(130 行,下游新增),用 httpUpstreamRecorder 桩验证 probeCindyBalanceModel 的传输结果映射:恰好填满 64KiB 后带尾随数据的成功前缀判 other(不信任截断体);HTTP 429 精确预算体、200+response.failed SSE、200+error SSE 三种形状都判 exhausted 且只发一次请求;201 状态下的终态 SSE 不被承认;成功必须是协议合法的 completed Responses(JSON 或 SSE),空体/HTML/空对象/缺 usage 均判 other;冲突或重复的 SSE 终态判 other。另有一例证明网关收到精确 429 时只向健康协调器投递 ExactBudget 信号、不内联探测也不写标记。被测对象为宿主执行器 cindy_balance_recheck.go 与 handleOpenAIAccountUpstreamError;探测模型由 cindyProbeTestModels 从插件计划取得。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L15-L21 newCindyBalanceProbeResponse helper; L23-L29 body padded to exactly cindyBalanceProbeMaxBodyBytes then 'trailing-response-data' -> cindyBalanceProbeOther; L31-L50 table http 429 exactCindyBudgetExceededBody / response.failed SSE / error SSE -> cindyBalanceProbeExhausted with len(upstream.bodies)==1.", - "L52-L71 TestExactCindyBudgetSignalDelegatesToHealthCoordinator: handleOpenAIAccountUpstreamError(429, exact body) returns true, repo.markCalls==0, CindyBalanceInsufficientAt nil, not runtime blocked, upstream.bodies empty, health.signals==[ExactBudget], health.accounts==[account.ID].", - "L73-L82 HTTP 201 + response.failed SSE -> Other; L84-L107 success matrix: valid JSON and valid SSE -> Success; empty, HTML, `{}`, completed-without-usage -> Other; L109-L130 SSE orders {exhausted,completed},{completed,exhausted},{exhausted,exhausted} -> Other.", - "Fixtures located with rg: newFirstClassCindyRateLimitAccount and cindyProbeTestModels (shared cindy test helpers in the service package), httpUpstreamRecorder, cindyRateLimitAccountRepoStub/cindyHealthCoordinatorRecorder (cindy_balance_shared_test.go). Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/cindy_balance_response_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cd042a3f26448fa8cfa0269178acfb421866d83e60d34fa12bff12b13f36571f", - "review_fingerprint": "cd042a3f26448fa8cfa0269178acfb421866d83e60d34fa12bff12b13f36571f", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "`//go:build unit` 表驱动测试(107 行,下游新增),验证宿主适配 IsCindyBalanceInsufficientResponse/ClassifyCindyBalanceInsufficient 经 cindy.health 调用 cindy-provider 插件后得到的信号:只有严格 Cindy 账号上的 429+error.type=budget_exceeded+error.code=\"429\"(字符串、大小写敏感)判 HTTP429;通用 402、缺 code、数字 code、错误 code/type、仅 message 文本、普通限流、畸形 JSON、非 Cindy 账号、其他状态码都判 None;200 带内 response.failed(response.error.*)→ResponseFailed、error 事件→ErrorEvent,顶层 error 放错位置、非终态事件、非 Cindy 账号被拒;终态事件形状在 201/400/503 下判 None,429 下 response.failed 形状判 None 而顶层 error 形状仍判 HTTP429。断言与 plugins/cindy-provider/catalog/health.go 的规则一致,证明宿主没有自带第二套判定。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L12-L47 TestIsCindyBalanceInsufficientResponse: 13 cases; only 'exact structured 429' and 'fields win without message' are true; nonCindy account (PlatformOpenAI, laxarouter base_url) with the exact body is false, as is StatusBadRequest on a Cindy account.", - "L49-L78 TestClassifyCindyBalanceInsufficientTerminalEvents: HTTP429 / ResponseFailed / ErrorEvent mapping for 429 body, 200 response.failed, 200 error; numeric code, misplaced top-level error, response.completed event and non-Cindy account -> CindyBalanceSignalNone.", - "L80-L107 terminal shapes under 201/400/503 -> None; 429 + response.failed shape -> None; 429 + top-level error shape -> HTTP429 (matches plugin rule Status==429 && budget(error.type,error.code) in catalog/health.go L21).", - "Subjects: cindy_balance.go L185/L249 -> plugin_cindy.go classifyCindyProviderResponse -> extension cindy.health (in unit tests provided in-process via the package TestMain, cindy_rollout_testmain_test.go L15). Fixtures newCindyRateLimitAccount/exactCindyBudgetExceededBody from cindy_balance_shared_test.go. Not executed." - ] - }, - { - "path": "backend/internal/service/cindy_balance_shared_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8406a2599f223650f6079b07cff97ee4b858e0320df6aaeadbdcf5466f87a054", - "review_fingerprint": "8406a2599f223650f6079b07cff97ee4b858e0320df6aaeadbdcf5466f87a054", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "Cindy 余额相关测试共享夹具(196 行,下游新增,无 build tag,供默认与 unit 标签两种构建共用):精确预算耗尽响应体常量、嵌入 AccountRepository 的 cindyRateLimitAccountRepoStub(记录 Mark/SetError 调用与可注入失败次数,MarkCindyBalanceInsufficientIfCredentialsMatch 直接转发并恒报凭据匹配)、cindyHealthCoordinatorRecorder(记录信号与账号 ID)、cindyBalanceRecoveryInterleavingCache(遗留 pending 与终态 episode 的精确匹配 CAS,afterGet/afterClear 钩子用于并发交错用例)以及 PlatformCindy/ProviderProfileCindyLaxaV1 账号构造器。只有桩与常量,不含断言,也不定义任何 Cindy 判定规则;归为 reference,随 cindy-provider 适配测试一起维护。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L10 exactCindyBudgetExceededBody (type budget_exceeded, code \"429\", ExceededBudget message); L15-L31 cindyRateLimitAccountRepoStub and cindyHealthCoordinatorRecorder structs with sync.Mutex counters.", - "L35-L109 cindyBalanceRecoveryInterleavingCache: legacyPending returns 64x'f' fingerprint and pending batch, ClearCindyBalancePending counts calls/honours legacyClearErr, GetCindyHealthTerminalPending copies the episode and fires afterGet once, ClearCindyHealthTerminalPendingIfMatch requires AccountID/Generation/EpisodeID/Fingerprint/Status equality then fires afterClear.", - "L111-L175 recorder/stub methods: MarkCindyBalanceInsufficient with markFailures budget and markChanged, MarkCindyBalanceInsufficientIfCredentialsMatch -> (changed, true, err), Clear/Preview/Delete no-ops, SetError counter; L177-L196 newCindyRateLimitAccount builds PlatformCindy/WirePlatformOpenAI/ProviderProfileCindyLaxaV1 api-key account from cindyCredentials() (cindy_identity_test.go L10) with pool_mode flag; newFirstClassCindyRateLimitAccount aliases it. Consumers: cindy_balance_*_test.go, cindy_balance_pending_test.go, cindy_balance_recheck_test.go. Not executed." - ] - }, - { - "path": "backend/internal/service/cindy_capability_catalog.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "8414571f3984ab5845e5834b43f1ae66c6b36ffc4b941026f96093915b40ae9d", - "review_fingerprint": "8414571f3984ab5845e5834b43f1ae66c6b36ffc4b941026f96093915b40ae9d", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_catalog_snapshot.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "ed3fa5d7dd796690d6f5a2b4f4fdc03ea43a4d6fa2f521fac9de22a2e5005071", - "review_fingerprint": "ed3fa5d7dd796690d6f5a2b4f4fdc03ea43a4d6fa2f521fac9de22a2e5005071", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_channel_catalog.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "5be0150f37c41f809e5359287272db9fe32ffd1ba6986a03488473a46dad9f40", - "review_fingerprint": "5be0150f37c41f809e5359287272db9fe32ffd1ba6986a03488473a46dad9f40", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "托管 \"Cindy Catalog\" 渠道的宿主投影(63 行,下游新增):数据库里的渠道只保存 features_config 标记 cindy_catalog_managed=cindy_laxa_v1,hydrateManagedCindyCatalogChannel 在读取时把 ModelMapping[PlatformCindy] 替换为插件返回的映射并清空 ModelPricing,使模型 ID 与价格只有插件一个事实来源;模型清单、映射与允许判断全部经 queryCindyCatalog 调用 cindy-provider 的 ManagedChannelProjection / ManagedChannelModelAllowed,本文件只保留标记识别与渠道名保留判断,无目录数据或规则副本。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L7-L11 CindyCatalogChannelName / MarkerKey cindy_catalog_managed / MarkerValue cindy_laxa_v1; L16-L26 hydrateManagedCindyCatalogChannel returns false for non-managed channels, otherwise sets channel.ModelMapping = {PlatformCindy: mapping} and channel.ModelPricing = nil.", - "L28-L35 isManagedCindyCatalogChannel requires FeaturesConfig marker string equality; L37-L49 cindyInternalPublicModelIDs / cindyManagedChannelProjection -> queryCindyCatalog(\"ManagedChannelProjection\") decoding (map[string]string, []string); L51-L55 cindyManagedChannelModelAllowed -> queryCindyCatalog(\"ManagedChannelModelAllowed\", model); L57-L63 name reservation (EqualFold) and marker presence helpers.", - "Rule ownership: the projection data is produced by plugins/cindy-provider catalog (ManagedChannelProjection/ManagedChannelModelAllowed methods, located with rg); host keeps only the marker contract. Process-level query with 1s timeout via queryCindyCatalog (cindy_capability_catalog.go L61-L80). Not executed." - ] - }, - { - "path": "backend/internal/service/cindy_channel_catalog_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c1de02b24b5896c3f20558d8ed6320743c06e4a5e22ac8ccd3f99586aaef0a67", - "review_fingerprint": "c1de02b24b5896c3f20558d8ed6320743c06e4a5e22ac8ccd3f99586aaef0a67", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "托管 Cindy 渠道投影的单元测试(46 行,下游新增,无 build tag):带标记的渠道 hydrate 后 ModelPricing 为空,且 ModelMapping[PlatformCindy] 对每个 PublicModel 能力同时包含 PublicID 与 LiveUpstreamID 到 LiveUpstreamID 的映射、非公开能力不出现、不含 gpt-5.4、gpt-5.4-mini 映射到 openai/gpt-5.6-luna、不触碰 PlatformOpenAI;普通渠道不被改写。断言以插件返回的 CindyCapabilities() 为基准,证明宿主投影与插件目录一致,属于宿主↔插件桥接测试;具体模型 ID 期望值来自插件目录数据。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L9-L33 TestHydrateManagedCindyCatalogChannelUsesCanonicalCatalog: channel with FeaturesConfig marker -> hydrate true, ModelPricing empty; loop over CindyCapabilities(): PublicModel -> mapping[PublicID]==mapping[LiveUpstreamID]==LiveUpstreamID, else both keys absent; NotContains gpt-5.4; mapping[\"gpt-5.4-mini\"]==\"openai/gpt-5.6-luna\"; ModelMapping[PlatformOpenAI] nil.", - "L35-L46 TestHydrateManagedCindyCatalogChannelLeavesOrdinaryChannelUntouched: channel without marker -> false, ModelMapping unchanged, ModelPricing empty.", - "Subjects: cindy_channel_catalog.go hydrateManagedCindyCatalogChannel/cindyManagedChannelProjection and cindy_capability_catalog.go CindyCapabilities (both plugin-backed via cindy.catalog, served in-process by the package TestMain). t.Parallel used; not executed." - ] - }, - { - "path": "backend/internal/service/cindy_codex_client_version.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "86c619ee1f9411efa2682d6a8d9f4e24bff1af69e7143119cca85cdeb067f0dd", - "review_fingerprint": "86c619ee1f9411efa2682d6a8d9f4e24bff1af69e7143119cca85cdeb067f0dd", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "全文31行:只限制已提供client_version的canonical semver最低0.147.0,空值保持原可选查询兼容;不按版本选择模型、改价格或发请求。门槛属于宿主已实现ModelInfo wire合同(错误仅含固定最低版本),非第二份provider目录/默认模型策略。", - "evidence": [ - "artifacts/evidence/v027-cindy-policy-admission-decode-review.json", - "Full-file source reads 3108fc/090a5b/44501b/4e896c plus current patch and source-hash verification", - "No generic filename or test-name-only closure" - ] - }, - { - "path": "backend/internal/service/cindy_duplicate_inventory.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "20199b5af5343960ae19be70e465fffdd788095428e70ffb5f46e52d71ce07a9", - "review_fingerprint": "20199b5af5343960ae19be70e465fffdd788095428e70ffb5f46e52d71ce07a9", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "凭据归一和摘要留宿主,插件只接收哈希与生命周期事实;输出必须完整且唯一覆盖每个输入重复身份的成员。", - "evidence": [ - "backend/internal/service/cindy_duplicate_inventory_test.go", - ".downstream/implementation-v0.2.7.md#可复用验证" - ] - }, - { - "path": "backend/internal/service/cindy_duplicate_inventory_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "663f47e2198f976e0a87177dff28362f43fefea5128c3e3f5cf4187723106f42", - "review_fingerprint": "663f47e2198f976e0a87177dff28362f43fefea5128c3e3f5cf4187723106f42", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "Cindy 重复身份清单的单元测试(34 行,下游新增,无 build tag):三个 base_url 大小写/尾斜杠不同但同一 api_key 的账号归为一组,建议归属者为最早创建的 Active 账号(ID 3),其余按 ID 升序列出,IdentityHash 为 64 位十六进制且不含明文密钥;全部为 Disabled 的组不选择归属者(ProposedOwnerID 为 0)。被测对象 BuildCindyDuplicateIdentityInventory(cindy_duplicate_inventory.go)把账号身份散列成 extensionv1.CindyDuplicateCandidate 事实交给插件分组,宿主只做散列与结果核对,属宿主↔插件桥接;管理员处理器 handler/admin/account_cindy_duplicates.go 消费该结果。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L10-L23 TestBuildCindyDuplicateIdentityInventoryIsDeterministicAndRedacted: accounts 9 (Active, created +2h, base_url https://API.LAXAROUTER.ai/ with upper case and trailing slash), 3 (Active, base), 5 (Disabled, -1h) sharing api_key secret-key -> one group, ProposedOwnerID==3, OtherAccountIDs==[5,9], len(IdentityHash)==64, hash does not contain secret-key.", - "L25-L34 TestBuildCindyDuplicateIdentityInventoryDoesNotChooseTerminalOwner: two Disabled accounts -> one group with ProposedOwnerID==0 and OtherAccountIDs==[11,12].", - "Subject located with rg: cindy_duplicate_inventory.go L12 BuildCindyDuplicateIdentityInventory building extensionv1.CindyDuplicateCandidate facts (ID, IdentityHash, Status, Banned, Exhausted, CreatedAt, UpdatedAt) and reconciling plugin-returned groups (L46-L61); consumer handler/admin/account_cindy_duplicates.go L12/L23. The owner-selection rule is asserted here but implemented plugin-side; test not executed." - ] - }, - { - "path": "backend/internal/service/cindy_endpoint_scheduling_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cff09ab20f6f3d0bee43e52e15c8f2503c427fccfb9d1265f7cf94e99fe75734", - "review_fingerprint": "cff09ab20f6f3d0bee43e52e15c8f2503c427fccfb9d1265f7cf94e99fe75734", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 网关调度器针对严格 Cindy 账号的端点能力测试(304 行,下游新增,无 build tag):accountSupportsOpenAICapabilities 的模型×端点矩阵(免费 Gemini 支持 Messages/Responses/Chat,受限 Claude 与 image-only Gemini、受限 gpt-image-2 不可选,Luna 三端点皆可,隐藏搜索/自动评审模型对客户端不可选,公开 Responses 模型可做 alpha search);SelectAccountWithSchedulerForCapability 在 alpha search 下选中 Cindy 账号、拒绝 ProviderProfile 为 cindy_future_v2 的跨档账号而选 canonical、混合分组按端点门禁把 Claude/Responses 与 image-only/Chat 请求交给普通账号、Messages 能力选中 Cindy、混合 Messages 用 WithOpenAICindyRequestedModel 的原生模型判定资格与 DB 复核、图片按操作门禁(Edit 交给普通账号,仅 Cindy 时 selectAccountWithScheduler 报错)。被测对象是核心调度机制(openai_account_scheduler.go / openai_gateway_scheduling.go),模型能否服务某端点的事实来自 cindy-provider 插件目录(CindyFreePoolModelSupportsEndpoint 等垫片),测试里的模型期望值是插件目录数据。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S49-cindy-service-T1-review.json", - "L11-L27 cindyEndpointSchedulingAccount fixture (PlatformCindy, WirePlatformOpenAI, ProviderProfileCindyLaxaV1, api_key + laxarouter base_url); L29-L60 15-case matrix over accountSupportsOpenAICapabilities (openai_account_scheduler.go L2640, which consults CindyAlphaSearchModelAvailable L2646 / CindyFreePoolModelSupportsEndpoint L2660, L2689).", - "L62-L74 first-class search: gpt-5.6-luna true, CindyWebSearchModel false, claude-opus-5 false; L76-L100 SelectAccountWithSchedulerForCapability (L2207) with AlphaSearch selects account 51004; L102-L131 cross-profile candidate cindy_future_v2 with better priority is rejected in favour of canonical 51006.", - "L133-L180 mixed group: claude-opus-5/Responses and gemini-3-pro-image/Chat select the ordinary OpenAI account 51012; L182-L204 gemini-3.6-flash with Messages capability selects Cindy; L206-L257 WithOpenAICindyRequestedModel (openai_gateway_scheduling.go L47): openAIRequestedModelForAccount returns native model for Cindy and fallback for ordinary, isOpenAICompatibleAccountEligibleForRequest / resolveFreshSchedulableOpenAIAccount / recheckSelectedOpenAIAccountFromDB (L374, L1568, L1626) accept Cindy, scheduler selects Cindy while excluding ordinary.", - "L259-L304 images: SelectAccountWithSchedulerForImages (L2305) with gpt-image-2 + CindyEndpointImagesEdit selects ordinary account; with only Cindy and withOpenAICindyImageEndpoint(ImagesEdit) (L2620) selectAccountWithScheduler (L2339) for gemini-3-pro-image returns error and nil selection. Fixtures schedulerTestOpenAIAccountRepo/schedulerTestGatewayCache/schedulerTestConcurrencyCache from openai_account_scheduler_test.go L23; resetOpenAIAdvancedSchedulerSettingCacheForTest L2183. Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/cindy_feature_flags.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "8711a7c83d6963628fc53a2168d30374a96c72525d9c9c9b52c0ca61c616512a", - "review_fingerprint": "8711a7c83d6963628fc53a2168d30374a96c72525d9c9c9b52c0ca61c616512a", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "全文98行:环境只在初始化快照和Legacy*导出中读取,生产引用仅plugin_bundle种子;运行五类开关来自已启用插件配置,Image Studio/桥接独立于Cindy catalog。当前依赖helper在decode失败时已修为全零,不会忽略ok后保留部分true;保留旧一版别名,不恢复环境作为运行fallback。", - "evidence": [ - "artifacts/evidence/v027-cindy-policy-admission-decode-review.json", - "Full-file source reads 3108fc/090a5b/44501b/4e896c plus current patch and source-hash verification", - "No generic filename or test-name-only closure" - ] - }, - { - "path": "backend/internal/service/cindy_feature_flags_independence_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4a1c7c4167715d758292cbc3956b71b11d8656016a235f16300133b1559a50da", - "review_fingerprint": "4a1c7c4167715d758292cbc3956b71b11d8656016a235f16300133b1559a50da", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "下游新增(上游无此文件)的子进程隔离测试:用 os.Args[0] -test.run 重启测试二进制并用 withoutEnvironmentKeys 清洗环境,断言四个 Cindy 表面开关(catalog/search/image studio/responses image bridge)默认关闭且互不影响、Search 可用性只依赖 GATEWAY_CINDY_SEARCH_ENABLED 而非目录发布、以及目录发布回滚后 free-pool 永久白名单仍放行 gpt-5.6-luna 并拒绝 sol/terra/gpt-image-2/web-search/auto-review。被测函数 CindyCapabilityCatalogFeatureEnabled 等(cindy_feature_flags.go)经 currentCindyProviderConfig 调 cindy.features,CindyFreePoolModelAllowed 等(cindy_capability_catalog.go)经 queryCindyCatalog 调 cindy.catalog,规则本体在 plugins/cindy-provider/catalog/catalog.go 的 Registry 方法,因此这是宿主门面到插件的桥接测试,归 cindy-provider。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S50-cindy-service-T2-review.json", - "L14-L97 TestCindySurfaceFlagsAreIndependentAndDefaultOff + helper: 6-case matrix over CindyCapabilityCatalogEnabledEnv/CindySearchEnabledEnv/ImageStudioEnabledEnv/CindyResponsesImageBridgeEnabledEnv expecting 'false,false,false,false' by default; env scrub also removes the legacy CindyImageStudioEnabledEnv (L71).", - "L99-L157 search/catalog 2x2 matrix: CindyAlphaSearchModelAvailable('gpt-5.6-luna') true iff search flag on; when on, asserts 9 managed compatibility models and alias gpt-5.4-mini -> openai/gpt-5.6-luna (values live in plugins/cindy-provider/catalog/catalog_data.go and catalog.go L50).", - "L159-L197 free-pool allowlist survives catalog rollback: CindyFreePoolModelSupportsEndpoint/CindyFreePoolModelAllowed vs CindyModelSupportsEndpoint gate; core functions are queryCindyCatalog facades (cindy_capability_catalog.go L144-L172) delegating to Registry.CindyFreePoolModelSupportsEndpoint (plugins/cindy-provider/catalog/catalog.go L305-L336).", - "Flag getters (cindy_feature_flags.go L58-L98) read currentCindyProviderConfig()/currentImageToolsConfig() = invokeProcessExtensionCached 'cindy.features' (plugin_cindy.go L12-L21); in the test binary the invoker is the in-process fixture registered by plugin_prompt_fixture_test.go init() (L67-L74, L80-L82), which builds the real plugin module cindy.New() and applies LegacyCindyProviderConfig() = the env snapshot taken at package init (cindy_feature_flags.go L24-L36). That is why each case must run in a fresh subprocess. The child skips TestMain re-exec because cindyTestHelperActive() matches the *CINDY*HELPER* env name (cindy_rollout_testmain_test.go L41-L50).", - "No second executor: this file contains no catalog data or flag logic of its own. Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/cindy_feature_flags_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "73cb7838f3b8f9fb7d74bd82e278c074b9e87a83dbe6de4e174eff29ba85180e", - "review_fingerprint": "73cb7838f3b8f9fb7d74bd82e278c074b9e87a83dbe6de4e174eff29ba85180e", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "下游新增的 Cindy 灰度开关回滚测试(子进程模式)。TestCindyRolloutFlagsAreIndependentlyDisableable 在其余开关全开时分别关闭 balance/catalog/image,并在 helper 中断言宿主各路径随之关闭:余额回滚后 ClassifyCindyBalanceInsufficient 返回 None、replay buffer 与流式终止事件不再处理、不新建 runtime block,但 DB 标记 CindyBalanceInsufficientAt 仍使账号不可调度、以真实账号凭据指纹(CindyAccountIdentityFingerprint)绑定的旧 Redis pending 标记只做清理不覆盖 DB 状态;目录回滚后 ResolveCindyCapability/CindyPublicModelIDs 为空、strict Cindy 分组门禁关闭、账号级 model_mapping 恢复、Luna 仍经 free-pool 放行而 Sol 不放行、gpt-5.4-mini 兼容别名仍可定价(0.2e-6/1.2e-6)但账号层不接受未解析别名、普通 OpenAI 账号不受影响;图片回滚后文本能力保留而 gpt-image-2/bridge 关闭。TestCindyRolloutFlagDefaultsAndParsing 断言缺省/空/非法值回到 'true,false,false' 以及 legacy IMAGE_STUDIO 环境变量回退。所有开关与目录规则均由 plugins/cindy-provider 模块通过 cindy.features/cindy.catalog 提供,测试本身无业务数据,属于宿主门禁到插件配置的桥接测试;定价/调度/计费等被断言的宿主路径属 core,但本文件不证明上游缺陷修复。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S50-cindy-service-T2-review.json", - "L17-L50 cindyFeaturePendingStore stub over stubGatewayCache (openai_gateway_service_test.go L739) implementing GetCindyBalancePendingFingerprint/HasCindyBalancePendingBatch/ClearCindyBalancePending(IfFingerprintMatches); L213-L227 seeds it with CindyAccountIdentityFingerprint(account.Platform, account.Type, account.Credentials) (cindy_balance.go L279) for account ID 99001 and asserts isOpenAIAccountRequestRuntimeBlocked (openai_account_runtime_block_fastpath.go L1570) neither blocks nor keeps the legacy marker — real-identity binding of the cleanup path.", - "L52-L90 three rollback subprocesses (balance/catalog/image) via -test.run=^TestCindyRolloutFlagHelper$ with env scrub incl. legacy CindyImageStudioEnabledEnv; L161-L372 helper: balance case uses ClassifyCindyBalanceInsufficient/cindyBalanceReplayBufferEnabled (cindy_balance.go L249/L256), handleCindyBalanceTerminalEvent/isOpenAIAccountRuntimeBlocked (fastpath L609/L1306) and exactCindyBudgetExceededBody (cindy_balance_shared_test.go L10); catalog case uses classifyAuthenticatedStrictCindyGroup (cindy_group.go L166), Account.IsModelSupported/GetMappedModel, CindyFreePoolModelSupportsEndpoint, CindyCompatibilityMappedUpstreamModel, calculateOpenAIRecordUsageTokenCost with NewBillingService(&config.Config{}, nil), accountSupportsOpenAICapabilities (openai_account_scheduler.go L2640), openAIRequestedModelForAccount/WithOpenAICindyRequestedModel (openai_gateway_scheduling.go L47/L55); image case uses CindyImageModelCapabilities (cindy_capability_catalog.go L227) and CindyModelSupportsResponsesImageBridge (plugin_image_bridge.go L164).", - "L92-L159 defaults/parsing matrix: 'missing', 'empty', 'invalid' -> 'true,false,false' (balance default on per cindy_feature_flags.go L31, catalog/image default off), 'legacy fallback' proves CindyImageStudioEnabledEnv still enables Image Studio when ImageStudioEnabledEnv is absent (config.ResolveImageStudioEnabledFromEnvironment).", - "L374-L388 withoutEnvironmentKeys: case-insensitive env key filter shared with cindy_feature_flags_independence_test.go. Subprocess helpers skip TestMain re-exec because the helper env name contains CINDY+HELPER (cindy_rollout_testmain_test.go L41-L50); flags reach the plugin through the fixture invoker in plugin_prompt_fixture_test.go L67-L74 applying LegacyCindyProviderConfig().", - "Fixture credentials use placeholder 'not-exposed' (L253); no secret material. No business rule is duplicated here; catalog/pricing values asserted (9 models, 0.2e-6/1.2e-6) originate in plugins/cindy-provider/catalog/catalog_data.go. Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/cindy_group.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "3375d4231400e558a64e7196256d0f265a7b81cbf96a97fde1443af06fe0dff7", - "review_fingerprint": "3375d4231400e558a64e7196256d0f265a7b81cbf96a97fde1443af06fe0dff7", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_group_identity_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b1d37c52975062b6afd577616cb19df566bc3e05325692c9153b421254d08fd7", - "review_fingerprint": "b1d37c52975062b6afd577616cb19df566bc3e05325692c9153b421254d08fd7", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_group_materialized_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "64c0d7e92954258e4b725772f6dc63ccfe672114bec847414c0fbd6f684f8527", - "review_fingerprint": "64c0d7e92954258e4b725772f6dc63ccfe672114bec847414c0fbd6f684f8527", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_health.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "92639c255418b1fa8f04c733a395897399d8d6533579061b81eae9d1a3bc3f36", - "review_fingerprint": "92639c255418b1fa8f04c733a395897399d8d6533579061b81eae9d1a3bc3f36", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_health_policy_scope_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8f5432e1378748b227ab30cce62924ca5d18cf1f567b8095d24f86f487373a51", - "review_fingerprint": "8f5432e1378748b227ab30cce62924ca5d18cf1f567b8095d24f86f487373a51", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "全文114行真实PluginManager+fake RPC:health/balance两wrapper在0/50/100灰度与两个分桶账号共12子例,校验拒绝时无RPC、允许时精确AccountID/不传canary;cache命中前撤销灰度或移除runtime均无旧决策;pre-create0及ordinary/legacy/nil边界保持。不运行health repository或实际进程。", - "evidence": [ - "artifacts/evidence/v027-cindy-policy-admission-decode-review.json", - "Full-file source reads 3108fc/090a5b/44501b/4e896c plus current patch and source-hash verification", - "No generic filename or test-name-only closure" - ] - }, - { - "path": "backend/internal/service/cindy_health_service_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2ff539992f79d958c2d124b142729e1b4440d693d97885318806b95af14a1019", - "review_fingerprint": "2ff539992f79d958c2d124b142729e1b4440d693d97885318806b95af14a1019", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_identity.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "aa81c6598a5565143e9d34e57ef92beb24c1e676b5c189974d07e1765559ae83", - "review_fingerprint": "aa81c6598a5565143e9d34e57ef92beb24c1e676b5c189974d07e1765559ae83", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_identity_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "87c0d35715525708080221bb2b7a001a6e6a7fd0280e195e8091760660c1a6b2", - "review_fingerprint": "87c0d35715525708080221bb2b7a001a6e6a7fd0280e195e8091760660c1a6b2", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_image_pricing_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "88f2c8d02401f4305bd3ea200be1dcfd309140ffe28abf9486ee4698fc8850bd", - "review_fingerprint": "88f2c8d02401f4305bd3ea200be1dcfd309140ffe28abf9486ee4698fc8850bd", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_independent_snapshot_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ba851a3974fcb73e73fe230f22546bae4c611de298e2cb29d9983671bc772779", - "review_fingerprint": "ba851a3974fcb73e73fe230f22546bae4c611de298e2cb29d9983671bc772779", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "完整原386行fixture/断言的双代理阅读记录与当前SHA一致;对默认/映射/描述符namespace、ordinary/pinned隔离、scope/catalog-off/缺V1与image默认提供真实目标断言。复用原八个方法的已有结果并明确本轮不重新执行,不将其外推为最终所有gateway模式验证。", - "evidence": [ - "artifacts/evidence/v027-cindy-snapshot-integration-review.json", - "artifacts/evidence/v027-astra-cindy-independent-metadata-review.json", - "artifacts/evidence/v027-astra-cindy-snapshot-second-review.json", - "Complete original eight-method fixture/assertion read only; no rerun or edit of this file." - ] - }, - { - "path": "backend/internal/service/cindy_native_count_tokens_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e6026bc62c82646f12a4acbc8875ef48a1052d27937709706a398438ab9147c1", - "review_fingerprint": "e6026bc62c82646f12a4acbc8875ef48a1052d27937709706a398438ab9147c1", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_native_image_snapshot_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "67d0d8b1cd0268e5ba934360bcbc262f6d064a803b6f465b374bcd139bc5ec50", - "review_fingerprint": "67d0d8b1cd0268e5ba934360bcbc262f6d064a803b6f465b374bcd139bc5ec50", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_native_messages_scope_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "37abeda6ce714861a1bd1a00c067ccb0ce01ff331221819ca71c3228d6669a81", - "review_fingerprint": "37abeda6ce714861a1bd1a00c067ccb0ce01ff331221819ca71c3228d6669a81", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "完整审阅新108行native Messages入口fake测试,实际红→绿验证账号admission及冻结价格引用。", - "evidence": [ - "0%与50%排除时无HTTP调用;50%包含正常透传1次并保留原model/upstreamModel/usage。", - "features和pricing RPC都携带实际account.ID,payload仍为{};同一个captured snapshot存在HTTP context和Gin Request.Context,可复制到异步billing且不被后续模块配置替换。", - "另一个账号不能复用价格引用;非Cindy保留exact identity error,且plugin invocation为空。仅synthetic gin/httptest recorder及fake upstream。", - "作为入口改动直接风险验证,测试使用独立Cindy module提供只读fixture;没有运行catalog包的既有测试集合。" - ] - }, - { - "path": "backend/internal/service/cindy_native_messages_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0d4cdc6ae3c85783076e5b7971aa9c60553f888418ff32ed791908ffb27dffb6", - "review_fingerprint": "0d4cdc6ae3c85783076e5b7971aa9c60553f888418ff32ed791908ffb27dffb6", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_pricing_snapshot.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "2dad2b619bdda9e001014dc1b33ed28ded9b9bceb6c326cfa600fa64febf71ad", - "review_fingerprint": "2dad2b619bdda9e001014dc1b33ed28ded9b9bceb6c326cfa600fa64febf71ad", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_pricing_snapshot_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4f91653e18d3fd833017a80e02a084e509fb3efbf24b7b6d3de6d700fe53f119", - "review_fingerprint": "4f91653e18d3fd833017a80e02a084e509fb3efbf24b7b6d3de6d700fe53f119", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Tests directly assert captured prices survive asynchronous boundaries and config updates, different accounts cannot reuse a snapshot, disabled providers block count-token/embedding entrypoints before IO, and the real manager's rollout gate rejects a cached policy for an excluded account while a prior bill retains its reference. Test bodies, fixture dispatch and expected costs were read; no model-quality claim is made.", - "evidence": [ - "New scope case configures real PluginManager bindings, populates cache, lowers rollout below stablePluginBucket(account.ID), expects admission errors before another plugin call, and preserves pending bill snapshot.", - "Existing async test calculates exact costs from the captured synthetic pricing and asserts another account has no reference; new-turn test preserves the old snapshot while current config changes.", - "Only new scope and directly affected async boundary cases ran this turn and passed; other unchanged cases reuse prior results." - ] - }, - { - "path": "backend/internal/service/cindy_probe_account_scope_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1a2365be97a39d2fd791b7ee9e4b27b3e769c31f1b6d60c944ba0756ac495b9f", - "review_fingerprint": "1a2365be97a39d2fd791b7ee9e4b27b3e769c31f1b6d60c944ba0756ac495b9f", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "完整审阅新209行fake测试,实际执行真实PluginManager scope gate;不是仅靠测试名判定。", - "evidence": [ - "9个场景:0%/50%排除/50%包含/100%/capability关闭/运行时不可用/计划错误/ctx取消/旧claim丢失。", - "明确拒绝要求实际HTTPUpstream.Do次数0、CompleteStage恰好1且stale/skipped_stale/networkFailure=false、无FinalizeRecovery/FinalizeExhausted调用、原claim/account信息未替换。", - "允许路径要求HTTP1次,plan/decide均真实账号ID;未知失败不结算stale。单独测试runtime.beginDrain取消实际HTTP request context,并禁止后续健康/状态写。", - "stub完整实现Do与DoWithTLS,无网络socket/DB/真实provider请求;任务状态不重领依据仍为既有repo终态选择SQL的静态核对。" - ] - }, - { - "path": "backend/internal/service/cindy_rollout_testmain_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "badbda2825d6be763a14a838f9b7f75a8b6e10c7331f570a86995e718d212553", - "review_fingerprint": "badbda2825d6be763a14a838f9b7f75a8b6e10c7331f570a86995e718d212553", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_snapshot_pricing_second_review_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cecc416a8d204727e008983d66c05fda7441b5cc0f66c4985ada18d8449fcd44", - "review_fingerprint": "cecc416a8d204727e008983d66c05fda7441b5cc0f66c4985ada18d8449fcd44", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_terminal_scheduling_isolation_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0f998af0ac3fa70495bbba8f707bad257e3da3d41405ea40d7ba3dae5940b707", - "review_fingerprint": "0f998af0ac3fa70495bbba8f707bad257e3da3d41405ea40d7ba3dae5940b707", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_text_billing.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "1c527762634948b9bbc8eef1f384a3e31ec2332ea8fa19b32ba6114ce0595240", - "review_fingerprint": "1c527762634948b9bbc8eef1f384a3e31ec2332ea8fa19b32ba6114ce0595240", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_text_billing_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a65a8f4adba99c4869dc07cb8f8060e61a58dfa0b98e7cd84d0d95dcc973aef0", - "review_fingerprint": "a65a8f4adba99c4869dc07cb8f8060e61a58dfa0b98e7cd84d0d95dcc973aef0", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_v4_catalog_contract_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "85ad6f8556d08f9e6e2af83fe6332208a233435b399ac9eb6e13f21b3c6b15bc", - "review_fingerprint": "85ad6f8556d08f9e6e2af83fe6332208a233435b399ac9eb6e13f21b3c6b15bc", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cindy_v4_catalog_fixture_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b50c8027e0704f189c05ea482b3b0896b61e4b4e839e912f6de47955493766dd", - "review_fingerprint": "b50c8027e0704f189c05ea482b3b0896b61e4b4e839e912f6de47955493766dd", - "review_status": "pending" - }, - { - "path": "backend/internal/service/cn_provider_balance_check_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d99dd1ee603292e16ebb90a40e7752a8091660e656494638fc5d02cb9f276722", - "review_fingerprint": "d99dd1ee603292e16ebb90a40e7752a8091660e656494638fc5d02cb9f276722", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "国产供应商账号周期探测服务:ticker 驱动 runOnce,按平台列出账号,跳过 Ollama Cloud 账号,coding plan 账号以 4 并发探测滚动窗口并落快照,kimi/deepseek 的 payg 账号查余额;余额低于阈值(双币种全部低于才算)且账号可调度时写入带 cnBalanceLowReason 前缀的临时停调,冷却 2× 检测周期。下游相对上游 aea725f 只改 checkOne 的恢复分支:把无条件 ClearTempUnschedulable 改为 TempUnschedGuardedClearRepository.ClearTempUnschedulableIfMatch,以本轮读取到的 (reason, until) 快照做 CAS,仓库不支持或快照已被并发改写时跳过并等下一轮,修复了余额探测可能误清其它子系统或新一轮停调的陈旧状态竞态,是核心调度机制的正确性修正。所有读写都以 account.ID 为键。plugins/account-tools 无余额/停调逻辑。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S21-svc-gateway-billing-1-review.json", - "Read L1-L300: L60-L97 Start/Stop with stopOnce + WaitGroup; L99-L194 runOnce collects targets (L120 IsOllamaCloudUsageAccount skip, L125 IsCodingPlan, L131 payg only for non-zhipu/minimax schedulable accounts), budget 30s+15s/batch+5s/payg capped at 300s (L157-L161), semaphore of 4 (L177-L189); L222-L267 checkOne; L269-L271 platforms kimi/deepseek; L275-L285 allCNBalancesBelowThreshold; L288-L300 cooldown.", - "git diff aea725f (14+/2-): L245-L262 replace accountRepo.ClearTempUnschedulable(ctx, account.ID) with type assertion to TempUnschedGuardedClearRepository and ClearTempUnschedulableIfMatch(ctx, account.ID, account.TempUnschedulableReason, *account.TempUnschedulableUntil); !ok and !applied paths log and return cnBalanceNoChange.", - "Identity binding: pause (L237 SetTempUnschedulable) and clear (L254) both use the listed account's own ID and its snapshot fields; the reason-prefix check (L248) keeps other subsystems' pauses untouched. rg over plugins/account-tools for balance/SetTempUnschedulable: none, so no duplicated executor. No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/cn_provider_balance_check_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0b2cf706fb7cbc3ee6db649ac7e427a52402005a61ba1f32bbcc9556de1d9151", - "review_fingerprint": "0b2cf706fb7cbc3ee6db649ac7e427a52402005a61ba1f32bbcc9556de1d9151", - "review_status": "pending" - }, - { - "path": "backend/internal/service/codex_ticket_lifecycle.go", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "829d07fa1ed71214fd90c03c717c8d2f53c151e1d53fd00d3929b4305f189ec5", - "review_fingerprint": "829d07fa1ed71214fd90c03c717c8d2f53c151e1d53fd00d3929b4305f189ec5", - "review_status": "pending" - }, - { - "path": "backend/internal/service/codex_ticket_manual.go", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "f90e26af3a0403630a7c3fece1266f928bc98e6626c87044ab5ad62a95f3788b", - "review_fingerprint": "f90e26af3a0403630a7c3fece1266f928bc98e6626c87044ab5ad62a95f3788b", - "review_status": "pending" - }, - { - "path": "backend/internal/service/codex_ticket_manual_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2069f5a26d4669d9d6a3f92516391b2d82d5a5186c2017c2fdf6dfdef8062648", - "review_fingerprint": "2069f5a26d4669d9d6a3f92516391b2d82d5a5186c2017c2fdf6dfdef8062648", - "review_status": "pending" - }, - { - "path": "backend/internal/service/codex_ticket_plugin.go", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "0518e7822c0f8e0bc42c7ee025b3732009e5dcec366ef62c98f28b670e8c0d93", - "review_fingerprint": "0518e7822c0f8e0bc42c7ee025b3732009e5dcec366ef62c98f28b670e8c0d93", - "review_status": "pending" - }, - { - "path": "backend/internal/service/codex_ticket_proxy.go", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "9e5ef45eefcea752870bf2fbf7ff0d46fe901e75d218fbb31ece7b6ce09bfb45", - "review_fingerprint": "9e5ef45eefcea752870bf2fbf7ff0d46fe901e75d218fbb31ece7b6ce09bfb45", - "review_status": "pending" - }, - { - "path": "backend/internal/service/codex_ticket_proxy_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5b9d389811d0ed1fa2edd7a46b214791ef256226d884d2f6e90e3c5743dd6a20", - "review_fingerprint": "5b9d389811d0ed1fa2edd7a46b214791ef256226d884d2f6e90e3c5743dd6a20", - "review_status": "pending" - }, - { - "path": "backend/internal/service/composite_platform_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b14e9891214f79e48de420131942d23039317a28812657bf6364c098ca1edd89", - "review_fingerprint": "b14e9891214f79e48de420131942d23039317a28812657bf6364c098ca1edd89", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "核心 composite 分组模型归属/平台探测测试:按账号精确映射解析归属(通配与空映射不声明、跨平台歧义)、NewGatewayService 装配 resolver、DetectModelPlatform 表、QuotaPlatform 解析、调度器 canonical 桶。下游相对上游新增:显式账号映射 MiniMax-M3→deepseek 必须优先于新 MiniMax 探测器;canonical 桶集合加入 PlatformCindy。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestNewGatewayServiceWiresCompositeModelOwnershipResolver L106-L159 (delta L112,L154-L158 MiniMax-M3 precedence); TestCompositeGroupSchedulerHasAllCanonicalPlatformBuckets L215-L228 (delta adds PlatformCindy L225)", - "TestResolveCompositeModelOwnership* L21-L104 and TestDetectModelPlatform L161-L201 unchanged vs upstream", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/content_moderation_runtime_cache_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a4385abf2df49a0d99df1190418cc370d838f151116ffea2c2f10788b3bc305c", - "review_fingerprint": "a4385abf2df49a0d99df1190418cc370d838f151116ffea2c2f10788b3bc305c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "核心内容审核运行态快照缓存测试:设置只读一次、UpdateConfig 立即生效并胜过初始加载/进行中的刷新、刷新失败保留旧配置并退避、未变配置复用 matcher、并发读写安全。下游相对上游把“刷新失败保留旧配置”用例从 time.Nanosecond TTL 改为 time.Minute 并手工把 loadedAt 回拨 2 分钟触发过期,消除 Windows 单调时钟步进导致的不稳定;断言语义不变。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestContentModerationRuntimeSnapshotRefreshFailureKeepsStaleConfig L263-L294 (delta L268 TTL time.Minute, L275-L279 manual expiry, comment L285)", - "Other suites L158-L261, L296-L462 unchanged; subject ContentModerationService.Check/UpdateConfig runtime snapshot", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/deepseek_pricing.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d1aac235c7c3284da379b94b91faaa33a28843ce8e3c757eeceb69e717f8d635", - "review_fingerprint": "d1aac235c7c3284da379b94b91faaa33a28843ce8e3c757eeceb69e717f8d635", - "review_status": "pending" - }, - { - "path": "backend/internal/service/deepseek_pricing_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f2cd6a118fc8d0d78150102d3c0c8c6e8633a9d21329b976cecc4f5661e06eee", - "review_fingerprint": "f2cd6a118fc8d0d78150102d3c0c8c6e8633a9d21329b976cecc4f5661e06eee", - "review_status": "pending" - }, - { - "path": "backend/internal/service/domain_constants.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "62435bad1ae5b2651efa724bde826d7173346d1c5951b66045644832961f97ec", - "review_fingerprint": "62435bad1ae5b2651efa724bde826d7173346d1c5951b66045644832961f97ec", - "review_status": "pending" - }, - { - "path": "backend/internal/service/domain_constants_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1829e1ec13e6657f0d20aa58e42c975ed861f236cabcac0d552905d630caae42", - "review_fingerprint": "1829e1ec13e6657f0d20aa58e42c975ed861f236cabcac0d552905d630caae42", - "review_status": "pending" - }, - { - "path": "backend/internal/service/email_service_smtp_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b86ec2cfcff982cd2c015ef66aed86c07979ca2cb95974157ea8c71ccf5a3eab", - "review_fingerprint": "b86ec2cfcff982cd2c015ef66aed86c07979ca2cb95974157ea8c71ccf5a3eab", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "核心 EmailService SMTP 连接形态测试(unit tag,内置最小假 SMTP 服务器):隐式 TLS(465)、UseTLS 时隐式失败自动降级强制 STARTTLS(587)、服务器不支持 STARTTLS 时报错且绝不把 AUTH 凭据发到明文、UseTLS=false 机会式 STARTTLS、纯明文、发送全流程。下游相对上游唯一改动是 L318 在 t.Fatal 后补 return(nilness lint),断言不变,按静态参考材料归档。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "fakeSMTPServer L56-L266; TestSMTPConnectionMandatoryStartTLSRefusesPlaintext L311-L326 asserts no AUTH over plaintext (delta `return` L318); StartTLS fallback L295-L308 asserts >=2 connections", - "git diff vs aea725f = single lint `return`; substance identical to upstream", - "Test source read statically, not executed; does not prove a downstream fix." - ] - }, - { - "path": "backend/internal/service/gateway_anthropic_apikey_passthrough_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9cdd6781c5eeb9b4ba5a06a432e0d046fa516104ab770c34223d6dcec7138979", - "review_fingerprint": "9cdd6781c5eeb9b4ba5a06a432e0d046fa516104ab770c34223d6dcec7138979", - "review_status": "pending" - }, - { - "path": "backend/internal/service/gateway_anthropic_passthrough.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "beaa732fc6a293fffb1994480632e87a695acadb1d15157ec3991af201098c26", - "review_fingerprint": "beaa732fc6a293fffb1994480632e87a695acadb1d15157ec3991af201098c26", - "review_status": "pending" - }, - { - "path": "backend/internal/service/gateway_count_tokens.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c759156e031f5814e11a6d81085ab95b5c4a2413a61edf290e325aed8fba27fd", - "review_fingerprint": "c759156e031f5814e11a6d81085ab95b5c4a2413a61edf290e325aed8fba27fd", - "review_status": "pending" - }, - { - "path": "backend/internal/service/gateway_forward_as_chat_completions.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9cc5d422a5f31fe42b99621e9d8461d278fcb329b7d866c621370a782c150823", - "review_fingerprint": "9cc5d422a5f31fe42b99621e9d8461d278fcb329b7d866c621370a782c150823", - "review_status": "pending" - }, - { - "path": "backend/internal/service/gateway_model_availability.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ca3ca4ac18358ae3d719f5eae42ba5ee83adb1585b1e79b3444298a7ba8935da", - "review_fingerprint": "ca3ca4ac18358ae3d719f5eae42ba5ee83adb1585b1e79b3444298a7ba8935da", - "review_status": "pending" - }, - { - "path": "backend/internal/service/gateway_model_availability_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e09ff115c093c064435572c60faef8173b265fb290bf4d2b6c24785a72c955c8", - "review_fingerprint": "e09ff115c093c064435572c60faef8173b265fb290bf4d2b6c24785a72c955c8", - "review_status": "pending" - }, - { - "path": "backend/internal/service/gateway_multiplatform_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2e987c7d76bdfb1d8f590f04154e33768b9e4693cd430f1389bfeaff47ff52e7", - "review_fingerprint": "2e987c7d76bdfb1d8f590f04154e33768b9e4693cd430f1389bfeaff47ff52e7", - "review_status": "pending" - }, - { - "path": "backend/internal/service/gateway_profit_control.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "de9827b2c6e18144d10b26d3f91f5d2e2b4761d95acaaa06fb659ab4cb572aba", - "review_fingerprint": "de9827b2c6e18144d10b26d3f91f5d2e2b4761d95acaaa06fb659ab4cb572aba", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "通用 Gateway token 请求利润门构造;入口固定 dormant,读分组前清除私有 context gate 后返回。;其余定价、平台识别、分组解析与数学逻辑未改。", - "evidence": [ - "Full source/diff review and exact test selectors: artifacts/evidence/v027-astra-dormant-profit-review.json", - "Canonical request/turn/gateway boundaries remain dormant; old columns, saved multipliers, pricingAt and private arithmetic are retained. No model requests or live data reads." - ] - }, - { - "path": "backend/internal/service/gateway_profit_control_v2_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "322e0ee3a40a46519a59bcaa516851a147dead54db7bc8eac8c9523ee3d218c1", - "review_fingerprint": "322e0ee3a40a46519a59bcaa516851a147dead54db7bc8eac8c9523ee3d218c1", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "五平台 token 定价、composite billing、mixed/routed/load-aware selection、failover 显式排除、sticky、handler context 和 image intent 保持;只退休利润准入。", - "evidence": [ - "Full source/diff review and exact test selectors: artifacts/evidence/v027-astra-dormant-profit-review.json", - "Canonical request/turn/gateway boundaries remain dormant; old columns, saved multipliers, pricingAt and private arithmetic are retained. No model requests or live data reads." - ] - }, - { - "path": "backend/internal/service/gateway_scheduling.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "08a70a653fd1931e5cf1c752f78e16f6ecaf0cd295f7ee1b6f51560140c13ef3", - "review_fingerprint": "08a70a653fd1931e5cf1c752f78e16f6ecaf0cd295f7ee1b6f51560140c13ef3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "网关账号选择与负载感知调度:三层粘性/路由/负载选择、窗口费用与 RPM 批量预取、混合调度、单平台选择、选择失败诊断,属宿主通用调度机制。下游相对上游 aea725f 仅 50 行:两处负载批量查询把 MaxConcurrency 从 EffectiveLoadFactor() 回退为 Concurrency(2f5350681 引入,见 finding);resolveGatewayGroup 新增 Cindy 源分组回退身份守卫且 Cindy 分组不跟随 fallback(守卫分支不可达,见 finding);newSelectionResult 叠加 attachSelectionRuntimeBreakerProbe(ctx 无 probe 时原样返回);四处 require_privacy_set 过滤不再对共享账号 SetError;选择失败统计删去 profit_threshold/profit_invalid_account_rate 计数(见 finding)。Cindy 守卫只是宿主侧隔离判断,规则函数 providerGroupIdentityCompatible 位于 provider_identity.go,未发现插件侧第二份实现;仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L2656 to EOF in sequential chunks; git diff aea725f -- gateway_scheduling.go = 50 changed lines in 12 hunks (L441, L712, L929-L953, L1586-L1591, L1982-L1986, L2095-L2099, L2242-L2246, L2356-L2360, L2425-L2436, L2454-L2471, L2502-L2507, L2587-L2598).", - "Call chain: attachSelectionRuntimeBreakerProbe (openai_account_runtime_block_fastpath.go:146) returns selection unchanged when ctx carries no openAIRuntimeBreakerProbeContext; attachSelectionProfitGate/openAIProfitControlVetoReason (openai_profit_control.go:296/322) and isGatewayAccountProfitEligible (gateway_profit_control.go:107) exist upstream too; providerGroupIdentityCompatible (provider_identity.go:115) also used by admin_group.go:554/1136.", - "EffectiveLoadFactor(): upstream account.go:168 and upstream gateway_scheduling.go:441/712 use it; downstream openai_gateway_scheduling.go:1340, openai_account_scheduler.go:1548/1728 use it; only this file's Anthropic/Gemini path was reverted (git log -S → 2f5350681).", - "Privacy filter: upstream mutated shared account health via accountRepo.SetError in 4 loops; downstream only `continue`s (comments L1982-L1983 etc.); RequirePrivacySet still covered by openai_load_sticky_privacy_test.go / openai_guardian_affinity_test.go (read only by filename, not reviewed here).", - "Not claimed: no test execution, no runtime verification of load-rate ordering; findings F1-F3 recorded above." - ] - }, - { - "path": "backend/internal/service/gateway_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a08ba70007e3e6e7e012f6d36fc4373d15045d69738265ad99fd7c72092abb11", - "review_fingerprint": "a08ba70007e3e6e7e012f6d36fc4373d15045d69738265ad99fd7c72092abb11", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "GatewayService 类型、GatewayCache/ForwardResult/UpstreamFailoverError 合同、粘性会话哈希、GetAvailableModels、模型列表缓存失效与调试日志等宿主通用代码。下游相对上游:GatewayCache 增加原子 DeleteSessionAccountIDIfMatches(repository/gateway_cache.go:89 实现,openai_sticky_compat.go:219 调用);新增 OpenAI 运行时熔断探测的可选 Redis 存储接口与 AccountSelectionResult 私有租约字段;UpstreamFailoverError 增加 ClientErrorCode/Type/Param、SuppressAccountHealthPenalty(ShouldReportAccountScheduleFailure 据此不记账号健康)及 CindyBalanceInsufficient/CindyHTTPToWSV2FirstTurn 标记;GatewayService 新增 cindyHealth/usageCache/usageCommitObserver 及 setter(wire.go:136/348-351 注入);GetAvailableModels 对 Cindy API key 账号只发布请求期 LoadCindyCatalogSnapshot(经 invokeProcessExtensionCached 调插件 cindy.catalog,无编译表回退)的 PublicModelIDs,缓存值携带 cindyDependent/namespace,失效按 group|platform 维度扫描。Cindy 部分是消费插件快照的宿主胶水,core 未复制目录或定价。本记录基于 63a98c8cc 之后(fix(cindy): bind model mapping and pricing to request snapshots)的当前字节,sha a08ba700… 由本次自行计算,与切片 fa555430… 不同;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L1808 to EOF; git diff aea725f -- gateway_service.go = 252 lines (GatewayCache L465-L479, breaker store interfaces L503-L529, modelsListCacheValue L553-L564, AccountSelectionResult L612-L641, UpstreamFailoverError L733-L784, GatewayService fields/setters L818-L877, GetAvailableModels L1446-L1585, InvalidateAvailableModelsCache L1668-L1695).", - "Frozen-file SHA policy: HEAD 52424fb7a, last commit touching file 63a98c8cc, working tree clean; content_sha256/review_fingerprint = self-computed sha256 of current bytes (a08ba70007e3e6e7e012f6d36fc4373d15045d69738265ad99fd7c72092abb11).", - "Cindy glue chain: IsCindyAPIKeyAccount (cindy_identity.go:33); LoadCindyCatalogSnapshot (cindy_catalog_snapshot.go:47) validates schema/owner and derives Namespace = pluginID:sha256(snapshot); CindyHealthCoordinator interface (cindy_health.go:108); UsageCommitObserver func type and UsageCache.InvalidateAccount (account_usage_service.go:132/141).", - "Runtime breaker interfaces implemented by repository/gateway_cache.go and consumed by openai_account_runtime_block_fastpath.go / openai_account_scheduler.go (core scheduling), not by a plugin.", - "Not claimed: no runtime check of cache hit/miss behavior; the models cache is in-process go-cache so the 3-part key compatibility in InvalidateAvailableModelsCache is harmless leftover, not flagged." - ] - }, - { - "path": "backend/internal/service/gateway_service_bedrock_beta_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b3b8408a736fe777da46e2845e2b2d351a3053d45041f4bb9aa94e49e6e32b69", - "review_fingerprint": "b3b8408a736fe777da46e2845e2b2d351a3053d45041f4bb9aa94e49e6e32b69", - "review_status": "reviewed", - "decision": "upstream-covered", - "owner": "core-quota-and-protocol", - "reason": "resolveBedrockBetaTokensForRequest 的 beta 策略测试:断言 block 规则在 Bedrock 变换前拦截原始 advanced-tool-use token、filter 规则在变换后过滤 tool-search token、请求体自动注入的 computer-use/tool-search token 同样受 block 规则约束、无匹配规则时 computer-use token 正常放行。下游相对上游仅在三处 t.Fatal 后追加 return(静态分析空指针提示),断言与上游完全一致;被测对象是核心 Bedrock 协议逻辑。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L270 to EOF; 5 tests + betaPolicySettingRepoStub; git diff aea725f = +3 lines (`return` after t.Fatal at L81, L169, L215).", - "Subject resolveBedrockBetaTokensForRequest and BetaPolicySettings are upstream core; no downstream-specific assertion remains.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/gateway_service_subscription_billing_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fb03527ebdcaf903c23883a1fbe643f98626385c11cd921c374e3354f5116c5e", - "review_fingerprint": "fb03527ebdcaf903c23883a1fbe643f98626385c11cd921c374e3354f5116c5e", - "review_status": "reviewed", - "decision": "upstream-covered", - "owner": "core-quota-and-protocol", - "reason": "buildUsageBillingCommand 订阅计费测试:断言订阅模式 SubscriptionCost 取 ActualCost(2x/0.5x 倍率按倍率消耗额度,0 倍率不扣),余额模式 BalanceCost 取 ActualCost。下游相对上游仅在 t.Fatal 后追加 return,实质与上游一致;被测对象是核心计费命令构造(gateway_usage_billing.go:277)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L86 to EOF (//go:build unit); 4 table cases; git diff aea725f = +1 line (`return` after t.Fatal at L76).", - "Cross-checked against gateway_usage_billing.go L313-L318 (SubscriptionCost = ActualCost when IsSubscriptionBill && TotalCost>0, else BalanceCost = ActualCost).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/gateway_usage_billing.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "54455771279b5f8d38fdd710f9e6bdcdb6ec3d2a3a40afa883302b491bb42e04", - "review_fingerprint": "54455771279b5f8d38fdd710f9e6bdcdb6ec3d2a3a40afa883302b491bb42e04", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "RecordUsage 核心:用户/分组倍率与高峰因子、计费模型确定(渠道映射/请求模型/composite 具体模型回退/response_model 采纳三不变式)、费用计算、usage_log 构建、applyUsageBilling→repo.Apply 原子扣费与 legacy 兜底、user×platform 配额与低余额/账号额度通知。下游相对上游 36 行:detachStream/UpstreamContext 改用 detachPluginPolicyContext(去掉请求取消但保留插件策略取消信号);writeUsageLogBestEffort 返回是否确认落库并调用 MarkQuotaLogPersisted/Failed 更新配额活动追踪;仅在 repo.Apply 真正 applied 时 usageCache.InvalidateAccount,且 applied 并且日志落库后才触发 usageCommitObserver。usage_log 与计费命令均绑定 input.Account.ID/APIKey.ID/User.ID,RequestID+APIKeyID+payload 指纹去重防重复扣费,applied=false 时不触发缓存失效;文件内没有任何 Cindy 定价分支。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L1246 to EOF; git diff aea725f hunks at L525-L540 (detachPluginPolicyContext), L567-L611 (bool-returning writeUsageLogBestEffort + quota log marks), L870-L896 (applied gating of usageCache/usageCommitObserver).", - "Call chain: detachPluginPolicyContext (plugin_operation_context.go:20) cancels the detached ctx when any plugin policy signal ctx ends; MarkQuotaLogPersisted/MarkQuotaLogFailed (quota_activity.go:150/167) update the per-account quota activity receipt; UsageCache.InvalidateAccount (account_usage_service.go:141); repository CreateBestEffort (usage_log_repo_insert.go:169) is the synchronous-result best-effort writer.", - "Identity/double-charge check: buildUsageBillingCommand L277-L332 uses p.Account.ID/p.APIKey.ID/p.User.ID; applyUsageBilling L334-L366 returns applied=false on dedup (result.Applied=false) and only schedules last-used update; rg -i cindy on this file → no matches.", - "Not claimed: repository Apply SQL and the plugin policy signal producers were not reviewed here; no test execution." - ] - }, - { - "path": "backend/internal/service/gemini_chat_completions_compat_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e844a8d54967280981de9b92df28ba9acd315044d9f4f42cf9235181d55fa059", - "review_fingerprint": "e844a8d54967280981de9b92df28ba9acd315044d9f4f42cf9235181d55fa059", - "review_status": "pending" - }, - { - "path": "backend/internal/service/gemini_messages_compat_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "87a094f551c78baec90757e0e107a5a8aaea1d2ee5bb3b928044dd0d89495d00", - "review_fingerprint": "87a094f551c78baec90757e0e107a5a8aaea1d2ee5bb3b928044dd0d89495d00", - "review_status": "reviewed", - "decision": "upstream-covered", - "owner": "core-quota-and-protocol", - "reason": "Gemini 与 Chat Completions/Messages 兼容层测试:OAuth/APIKey 上游路由与响应格式、SSE 分块转换、函数工具 web_search 不被提升为内置搜索、cleanToolSchema 规范化($defs/可空类型/exclusiveMinimum/enum)、thoughtSignature 注入、unwrapGeminiResponse、extractGeminiUsage、ParseGeminiRateLimitResetTime、流式 tool→text 内容块闭合。下游相对上游仅两处 t.Fatalf 后追加 return,断言与上游一致;被测对象为核心 Gemini 协议桥接。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L1162 to EOF; git diff aea725f = +2 lines (`return` after t.Fatalf at L891 and L1037).", - "Subjects (GeminiMessagesCompatService.ForwardAsChatCompletions/Forward, cleanToolSchema, extractGeminiUsage, ParseGeminiRateLimitResetTime, handleStreamingResponse) are upstream core; nothing downstream-specific remains.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/gemini_multiplatform_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7f5303e382e1035312df08425fe6180f45151ae9e671a0ed34f368015d4335c8", - "review_fingerprint": "7f5303e382e1035312df08425fe6180f45151ae9e671a0ed34f368015d4335c8", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "GeminiMessagesCompatService 账号选择测试与 AccountRepository/GroupRepository/GatewayCache 的 mock:验证平台隔离、分组上下文复用与 Lite 查询、OAuth 优先、粘性会话命中/平台不匹配/不可调度时清理并回退、混合调度、排除账号、模型支持判断。下游相对上游仅为 mockGatewayCacheForGemini 补实现 GatewayCache 新增的 DeleteSessionAccountIDIfMatches(比较绑定账号后委托 DeleteSessionAccountID),属编译适配,不证明任何下游生产修复。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L1016 to EOF (//go:build unit); git diff aea725f = +7 lines (L308-L313 mock method).", - "Interface driver: GatewayCache.DeleteSessionAccountIDIfMatches added downstream in gateway_service.go:479; production implementation repository/gateway_cache.go:89; this mock is never exercised by the assertions in this file.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/gemini_oauth_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "88c335e24f4233e4fbba62fb205d37a83045d8c09b40726088636bf065eb6a8b", - "review_fingerprint": "88c335e24f4233e4fbba62fb205d37a83045d8c09b40726088636bf065eb6a8b", - "review_status": "reviewed", - "decision": "upstream-covered", - "owner": "core", - "reason": "GeminiOAuthService 测试:授权 URL 的客户端/回调策略、validateTierID 与 tier 规范化、AllowedTiers 提取、Google One 存储档位推断、不可重试错误分类、凭据构建、RefreshToken 重试/不可重试、RefreshAccountToken 各 oauth_type 路径与 unauthorized_client 回退、ExchangeCode 会话/state 校验。下游相对上游仅八处 t.Fatal 后追加 return,实质与上游一致;被测对象为宿主通用 OAuth 服务。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L1495 to EOF (//go:build unit); git diff aea725f = +8 lines (`return` after t.Fatal at L109, L886, L943, L968, L1227, L1389, L1413, L1441).", - "Mocks (mockGeminiOAuthClient, mockGeminiCodeAssistClient, mockGeminiProxyRepo, mockDriveClient) and all assertions are identical to upstream in substance.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/gpt56_prompt_source.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c96f7fc90d5f6bda35c065f1a30f389674c761e7eab96ad18424dfaf6d121a74", - "review_fingerprint": "c96f7fc90d5f6bda35c065f1a30f389674c761e7eab96ad18424dfaf6d121a74", - "review_status": "reviewed", - "decision": "adapter", - "owner": "prompt-skills", - "reason": "新增宿主侧业务系统提示词来源桥接:GitHubGPT56PromptSource.Fetch 与 ValidateBusinessSystemPromptSourceCandidate 均通过 invokePromptManagement 调用 prompt-skills 插件的 prompt.source.fetch / prompt.source.validate 操作,来源出处策略在插件内;本文件只保留错误哨兵、接口类型别名(extensionv1.PromptSourceCandidate)以及供仓储适配器使用的纯结构校验 ValidateBusinessSystemPromptSourceCandidateShape(十六进制长度、正文 sha256/字节数一致),不重跑插件策略,故无二次执行器。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "Fetch L25-L32 -> invokePromptManagement(ctx,'prompt.source.fetch') (plugin_prompt_management.go:16) -> plugins/prompt-skills/policy/management.go:182; Validate L34-L36 -> 'prompt.source.validate' (management.go:185)", - "Shape check L40-L56 is structural only (isLowerHex 40/64, ValidateBusinessSystemPromptBody hash/length); consumed by repository/business_system_prompt_repository.go:45,511 and wired at business_system_prompt_service.go:168", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/grok_credential_failure.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "deaadf633fe5e32ff925c1724e7e1a5d0c3b4de98ca5229a0b75a79ba9ac66e6", - "review_fingerprint": "deaadf633fe5e32ff925c1724e7e1a5d0c3b4de98ca5229a0b75a79ba9ac66e6", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 网关的 Grok OAuth 凭据获取与故障转移合同:失败分类(永久/瞬时/提供方级)、按账号快照(凭据 JSON、access/refresh token、_token_version、ProxyID)CAS 的 SetGrokCredentialErrorIfMatch / SetGrokCredentialTempUnschedulableIfMatch 持久隔离、并发刷新令牌复用、运行时封禁与回滚。下游相对上游仅改 blockGrokCredentialRuntime(L570-L614):改为基于 openAIAccountRuntimeBlockSourcesLocked 的分来源聚合,回滚只恢复本次试探性封禁自身的贡献,不再清掉 DB 镜像期限或更新的独立写入者,是核心正确性修正;所有状态变更均绑定 account.ID 与凭据快照。Grok 不属七个插件域。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L675 to EOF; git diff aea725f = one hunk L573-L614 replacing generation/until-based install+rollback with sources-based (hasIndependent/independentUntil/independentOwner, expire(), effectiveUntil()).", - "Identity binding: applyGrokCredentialAccountFailure L293-L452 locks per account (grokCredentialMutationLock), validates current row (validateCurrentGrokCredentialFailure L454-L507) and only mutates via *IfMatch CAS; CAS miss → resolveGrokCredentialCASMiss reuses a concurrently refreshed token.", - "Runtime-block helpers (openAIAccountRuntimeBlockSourcesLocked, openaiAccountRuntimeBlockSources, blockAccountSchedulingLocked) live in openai_account_runtime_block*.go (core OpenAI scheduling), verified by rg during this review.", - "Not claimed: no concurrency test executed; the lock-free window between mu.Unlock (L579) and rollback is intentionally guarded by owner/until equality." - ] - }, - { - "path": "backend/internal/service/grok_free_quota_gate_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e790cc76f67ca602c0f47ef58d9b0d76cb839d76ada5a47dde6b1e3d12c114fc", - "review_fingerprint": "e790cc76f67ca602c0f47ef58d9b0d76cb839d76ada5a47dde6b1e3d12c114fc", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 账号调度器的 Grok 免费额度软门测试:缓存未命中失败开放、后台刷新后仅拦截显式 FREE 的 OAuth 账号、统计查询失败/未知档位失败开放、用量回落后恢复、95% 默认门、selectByLoadBalance 应用软门、缓存清扫与离场账号淘汰。下游相对上游仅把首个用例改为 require.Eventually 等待过滤结果本身、并在锁内读取 repo.lastIDs/start,消除异步刷新的竞态;这是测试自身的时序修正,不证明生产行为修复。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L314 to EOF (//go:build unit); git diff aea725f = L84-L97 (Eventually on filter result; mutex-guarded reads of lastIDs/start).", - "Subjects filterGrokFreeQuotaAccounts / filterGrokFreeQuotaAccountsCore / resolveGrokFreeQuotaGateSettings / sweepGrokFreeQuotaGateCache are core scheduler code (grok_free_quota_gate.go; gateway_scheduling.go:1026/1126/1538 call filterGrokFreeQuotaAccountsForGateway).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/grok_quota_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3088bd6478e2742a2e93d395c532924528395883c2d7a1384a055171d64e36e9", - "review_fingerprint": "3088bd6478e2742a2e93d395c532924528395883c2d7a1384a055171d64e36e9", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "GrokQuotaService 测试:观测模型同步的 URL 安全策略与 CLI 头、fetchBilling 对 502/传输错误的单次重试、ProbeUsage 的限流头解析/快照存储/代理加载/429/脱敏、QueryQuota 免费账号走 grok-4.5 混合探测而付费仅走 billing、本地 24h 与账期窗口、探测去重、403 媒体资格信号、自动暂停判定。下游相对上游 76 行:x-grok-client-version 只断言非空且不再断言 User-Agent(CLI 版本改为动态解析);删除 quotaSnapshot 辅助,三处 QueryQuota 用例改为按路径计数并容忍成功后异步发出的 GET /v1/models。均为测试对异步时序与动态版本的容错调整,不证明生产修复。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L1307 to EOF (//go:build unit); git diff aea725f hunks at L136-L137, removed quotaSnapshot helper, L744-L773, L796-L814, L834-L851.", - "grokCLIVersion is still pinned in TestGrokQuotaServiceProbeUsageStoresHeaders L495, so the relaxed assertion only concerns the /models sync path.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/grok_upstream_errors_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4df4b681fb750fe56221b1be73ffd3b2279e2245c229ee535325826a18b97302", - "review_fingerprint": "4df4b681fb750fe56221b1be73ffd3b2279e2245c229ee535325826a18b97302", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Grok 上游错误处理测试:isGrokContentPolicyRejection 分类表、内容策略 403 与 SSE error 不改账号状态也不 failover、不套用通用临时封禁规则、媒体响应绕过自定义错误码、entitlement 403 默认 30 分钟冷却与 pool_mode 例外、配置规则优先于默认冷却。下游相对上游仅适配 failoverOpenAIUpstreamHTTPError 去掉 message 参数的签名变化(两处调用),断言不变。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L457 to EOF (//go:build unit); git diff aea725f = 2 call-site changes at L138 and L169-L171.", - "Subjects handleGrokAccountUpstreamError / shouldFailoverGrokUpstreamError / handleErrorResponse are core OpenAI gateway error handling; the signature change itself lives outside this slice.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/group.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ee6c97981f933b8b9db138f811af1ba6f145e4e546673716eae846f39f141ad5", - "review_fingerprint": "ee6c97981f933b8b9db138f811af1ba6f145e4e546673716eae846f39f141ad5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主 Group 领域模型及纯函数:图片/视频价格取值、模型路由匹配、高峰倍率 PeakMultiplierAt/Validate/Normalize、computePeakAwareMultipliers、利润控制 Validate/Normalize(配置层保留,运行期门已退役)。下游相对上游在 Group 上新增 WirePlatform/ProviderProfile 与 StrictCindyKnown/StrictCindy 字段(cindy-provider 身份由 provider_identity.go 解析、此处仅承载),并做注释清理与 validProfitControlRatio 位置调整;无行为分支变化。静态阅读,未执行构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "Group struct L18-L149: WirePlatform/ProviderProfile L23-L24, StrictCindyKnown/StrictCindy L38-L39 (delta); PeakMultiplierAt L322-L337; NormalizePeakRateConfig L378-L394; computePeakAwareMultipliers L400-L408", - "ValidateProfitControlConfig L427-L444 / NormalizeProfitControlConfig L452-L465 still used by admin_group.go:497,915 for stored config while runtime gate is disabled (openai_profit_control.go:77)", - "File statically reviewed only; no build run." - ] - }, - { - "path": "backend/internal/service/group_model_allowlist.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "536851cc0fe270ade8fc87489991ce5d14124b2123ce3438c613842da741848c", - "review_fingerprint": "536851cc0fe270ade8fc87489991ce5d14124b2123ce3438c613842da741848c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "上游已有的分组模型白名单(归一化、Allows 准入、FilterForListing 列表过滤)。下游相对上游仅新增候选形式 groupModelAllowlistLegacyOpenAIReasoningBase:仅当模型为裸名或 openai/ 命名空间、基名恰为 gpt-5.5-codex 且后缀属官方 effort 集合时,把旧 Codex 后缀别名等价为 gpt-5.5 用于白名单匹配;它只进入匹配候选,不改写请求归一化、账号映射或计费,属对上游白名单兼容性的核心修正。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "groupModelAllowlistCandidates L129-L150 adds candidate L148; groupModelAllowlistLegacyOpenAIReasoningBase L155-L172 (namespace guard L157-L160, base 'gpt-5.5-codex' L162-L165, effort set L166-L170)", - "Allows L95-L126 and FilterForListing L177-L229 unchanged vs upstream; matcher-only property asserted by group_model_allowlist_test.go:149-165", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/group_model_allowlist_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b71a15ed6fa3f04099ee6fbd98b8ec6a73b810128635d6475731bc293b2a4383", - "review_fingerprint": "b71a15ed6fa3f04099ee6fbd98b8ec6a73b810128635d6475731bc293b2a4383", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "分组模型白名单测试。下游相对上游新增 7 个负例(gpt-5.5-codex 无后缀、-max、未知家族、嵌套后缀、重复 effort、vendor/ 与 openai/vendor/ 命名空间均不得被猜测折叠)与 TestGroupModelAllowlistLegacyOpenAIReasoningEquivalenceIsMatcherOnly(官方 effort 集合与大小写/下划线拼写均命中 gpt-5.5 白名单,同时 NormalizeOpenAICompatRequestedModel 不改变路由模型标识),证明新增等价规则只作用于匹配器。既有归一化/Allows/FilterForListing 用例保留。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestGroupModelAllowlistAllows L88-L147 (delta negative cases L106-L112); TestGroupModelAllowlistLegacyOpenAIReasoningEquivalenceIsMatcherOnly L149-L165 (delta)", - "TestNormalizeGroupModelAllowlist L8-L86 and TestGroupModelAllowlistFilterForListing L182-L279 unchanged", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/group_model_capacity.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a39332b72d85c4068f212bdae161a08a0132f076b4110d0fc8a8dd6897be89c5", - "review_fingerprint": "a39332b72d85c4068f212bdae161a08a0132f076b4110d0fc8a8dd6897be89c5", - "review_status": "reviewed", - "decision": "plugin", - "owner": "model-policy", - "reason": "下游新增的请求级模型上下文容量投影:ApplyModelContextCapacityToFields 只改写 context_window/max_*/capacity_source|basis|reason 等容量字段、保留其它字段、protected 行不动、Codex 时钳制 auto_compact_token_limit;groupModelCapacityCatalog 一次性加载分组候选账号、composite 路由与渠道映射,按实际转发目标(passthrough/chat/messages dispatch 一致性)取候选最小值并给出 reason(group_minimum/ambiguous_*/no_model_candidate 等),投影后重算 ETag 且不改上游原始缓存。官方参考目录数据在 model-policy 插件(LookupOfficialModelContextCapacity→lookupExtensionCatalog),本文件是该插件领域业务规则在宿主内的执行体,未发现插件重复实现同一投影(非二次执行器)。见 findings:composite 候选平台列表漏 PlatformOpenCodeGo。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "ApplyModelContextCapacityToFields L18-L71; loadGroupModelCapacityCatalog L172-L202 (composite platform list L178); compositeTarget L213-L248; resolve L362-L454 (protected L374-L376,L407-L409; minima L427-L452); projectModelCapacityEnvelope L456-L489; Project* entry points L503-L604", - "Reference data lives in plugin: model_context_capacity.go:484-494 LookupOfficialModelContextCapacity -> lookupExtensionCatalog -> plugins/model-policy/catalog/catalog_data.go; restoreLiveCodexAutoCompactLimits used by openai_codex_models_service.go:2535", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/group_model_capacity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0cda304cd9eb0b517be7937153da4ac0c2a6f8af91a833984d5645e5abc4d3b3", - "review_fingerprint": "0cda304cd9eb0b517be7937153da4ac0c2a6f8af91a833984d5645e5abc4d3b3", - "review_status": "reviewed", - "decision": "plugin", - "owner": "model-policy", - "reason": "新增测试,覆盖 model-policy 容量投影的宿主执行规则:字段投影保留未知/protected 字段且幂等;候选池包含通配、未限制与临时限流账号但仅一次可用性查询;渠道映射与 passthrough 导致的端点目标歧义;composite 路由歧义与批量查询计数;OAuth/Cindy protected 行与账号查询失败回落默认并给 reason;max_input/output 保守取最小;Codex 投影刷新 ETag 而不改原始缓存、live 观测胜过快照但不胜过覆盖、变更过端点的账号 live 被拒;pinned 来源保护与合并顺序、来源身份为捕获值;provenance 克隆与缓存预算;MiniMax composite 显式路由优先;simple mode 用全平台池。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestApplyModelContextCapacityPreservesUnknownAndProtectedFields L72-L92; ...IncludesWildcardUnrestrictedAndTemporarilyBlockedCandidates L94-L113; ...CompositeAmbiguityAndBatchQueries L131-L154; ...ProtectedCandidatesAndQueryFailure L156-L170", - "TestCodexCapacityProjectionRefreshesETagWithoutChangingRawCache L197-L221; ...LiveWinsOverSnapshotButNotOverride L223-L237; ...RejectsLiveFromChangedAccountSource L239-L253; ...PinnedSourcesPreserveProtectedAndMergeOrder L255-L290; TestMiniMaxCompositeCapacity... L330-L366; TestGroupCapacitySimpleModeKeepsActualOpenAIFullPool L460-L478", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/group_peak_rate_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "54e3d49ba69415952f50c19d806091679493b9a7289f032b536e17612bf9a585", - "review_fingerprint": "54e3d49ba69415952f50c19d806091679493b9a7289f032b536e17612bf9a585", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "核心高峰倍率计费测试:PeakMultiplierAt 边界/禁用/时区/标准类型降级、ValidatePeakRateConfig 表、computePeakAwareMultipliers 叠加顺序(高峰只乘 token 倍率不影响图片)、认证快照往返保留 4 个 peak 字段。下游相对上游唯一改动是 L224 在 t.Fatalf 后补 return(nilness lint),断言不变,按静态参考材料归档。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestPeakMultiplier_GatewayBillingSequence L153-L205 (image multiplier unaffected by peak); TestPeakMultiplier_SnapshotRoundTrip L210-L239 (delta `return` L224)", - "git diff vs aea725f = single lint `return`; substance identical to upstream", - "Test source read statically, not executed; does not prove a downstream fix." - ] - }, - { - "path": "backend/internal/service/group_profit_platform_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": false, - "content_sha256": null, - "deleted_upstream_blob": "28a5f2290a7e0f4e5bb3ff37025fdf416eb526c1", - "review_fingerprint": "784b57018a1565343d985c095406522f6fd3b3a9ccd43c06e46de9ebd8c3576f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "空platform应归一为Anthropic、显式OpenAI保持原值,以及默认平台后enabled利润配置被允许。 默认平台实现仍保持;公开利润启用预期与现行退休API直接冲突,不能恢复旧组合测试以重新开放写入。", - "evidence": [ - "Exact deleted blob and replacement assertion mapping: artifacts/evidence/v027-astra-deleted-path-review.json", - "该已删文件及旧profit-preview均未运行;独立dormant证据记录限定服务回归。", - "Deletion basis: 5f216d1d07f091b8942aa70e3c5ee3d7fc4153fe", - "The bound dormant implementation is included with this review; its exact eight source SHA256 values were verified before import." - ] - }, - { - "path": "backend/internal/service/http_upstream_profile.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c7b302172ba31889fd07384b51020955ec8d17d37f4fc86846c7633f5254fb2a", - "review_fingerprint": "c7b302172ba31889fd07384b51020955ec8d17d37f4fc86846c7633f5254fb2a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "上游已有的 HTTP 上游传输 profile 上下文标记(profile 注入/读取白名单、禁止重定向标记、仅公网主机标记)。下游相对上游仅新增 HTTPUpstreamProfileOpenAIHarvest 常量并加入 FromContext 白名单;仓储层据此选用不复用连接的 H1 模式,但生产代码中没有任何调用方设置该 profile(Codex ticket harvest 路径未使用)——见 findings(低)。核心网关传输机制。静态阅读,未执行构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "Consts L9-L15 (delta L12 openai_harvest); HTTPUpstreamProfileFromContext whitelist L41-L46 (delta adds OpenAIHarvest); redirect/public-host markers L51-L75 unchanged", - "Consumer: repository/http_upstream.go:1018 -> upstreamProtocolModeOpenAIH1NoReuse; producers found via rg: only HTTPUpstreamProfileOpenAI and HTTPUpstreamProfileGrok are ever set in non-test code", - "File statically reviewed only; no build run." - ] - }, - { - "path": "backend/internal/service/http_upstream_profile_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ff80eed140a38bb3fbf9897c28a64a6aa0c14a61546666291a9319ed373a3d18", - "review_fingerprint": "ff80eed140a38bb3fbf9897c28a64a6aa0c14a61546666291a9319ed373a3d18", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "HTTP 上游 profile 上下文标记测试:默认 profile 不包裹 ctx、OpenAI/LongStream profile 往返、禁止重定向与仅公网主机标记(含 nil ctx 回退)且互不影响。下游相对上游新增 TestWithHTTPUpstreamProfile_OpenAIHarvest,证明新常量能经 WithHTTPUpstreamProfile/FromContext 往返(白名单已收录);它不证明生产路径会设置该 profile。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestWithHTTPUpstreamProfile_OpenAIHarvest L23-L28 (delta); DefaultKeepsContext L8-L14; RedirectsDisabled L37-L46; PublicHostsOnly L48-L60", - "Companion to http_upstream_profile.go finding: test-only producer of the harvest profile", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/image_studio_artifact.go", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "906916fae7d72abde7baacb209b31352f05f2e7477f15156a3991939fafac46e", - "review_fingerprint": "906916fae7d72abde7baacb209b31352f05f2e7477f15156a3991939fafac46e", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "下游新增 Image Studio 产物文件存储 ImageStudioArtifactStore:保存前按魔数嗅探 PNG/JPEG/WEBP 并要求声明 content-type 一致、≤20MB;在互斥锁内读取用户/全局用量并按 250MB/2GB 配额 fail-closed;随机 16 字节十六进制不透明存储键、O_EXCL 0600 独占创建、写失败即删除;Open/Read/Remove 一律先经正则校验存储键(防路径穿越),Read 限长。属 image-tools 领域的格式/配额规则在宿主内的存储执行体,插件 policy 模块只处理 plan/validate/models 不重复这些规则。Save 的 expiresAt 参数未使用(过期由仓储记录),无行为影响。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "imageStudioStorageKeyPattern L18; Save L34-L94 (quota check L55-L62, O_EXCL 0600 L75, cleanup L81-L90); path() key validation L142-L147; validateImageStudioImage L157-L180", - "Wired at service/wire.go:221 NewImageStudioArtifactStore; consumed through ImageStudioFileStorage by ImageStudioService and ImageStudioRuntime; plugins/image-tools/policy/module.go has no storage/quota/format rules", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/image_studio_artifact_test.go", - "candidate_owner": "image-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7bab42a44698dced4ce9ef309c070f8c61a11ca25c651049145bf6493a854aaa", - "review_fingerprint": "7bab42a44698dced4ce9ef309c070f8c61a11ca25c651049145bf6493a854aaa", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "新增单元测试(unit tag):产物存储写入经校验的 PNG 后存储键不含路径分隔符、字节数正确且可原样读回;用户/全局配额已满时在写盘前以 storage_quota_exceeded 拒绝;声明 content-type 与实际内容(JPEG 魔数 vs image/png)不一致时以 invalid_image 拒绝。证明 image-tools 存储规则的宿主实现。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestImageStudioArtifactStoreWritesOpaqueValidatedFile L23-L39; ...RejectsQuotaBeforeWriting L41-L52 (usage at limit-1); ...RejectsMismatchedContentType L54-L62", - "Stub imageStudioUsageRepoStub L14-L21 supplies StorageUsage only", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/image_studio_job.go", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "ada9c44b56f3e0473f0593cdd158d72e9da0cf3a2685feeef5f9181c37d44aa7", - "review_fingerprint": "ada9c44b56f3e0473f0593cdd158d72e9da0cf3a2685feeef5f9181c37d44aa7", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "下游新增 Image Studio 领域模型:模型/最大张数常量取自 extensionapi/v1,宿主定义 20MB 单图、2GB 全局、250MB 用户配额与 24h 文件/30d 元数据保留;job/item/artifact 状态枚举、ImageStudioError、Create/Claim/Execution DTO、Repository/FileStorage/Executor 接口。JSON 输出隐藏 UserID/Prompt/StorageKey。ValidateImageStudioCreateInput 委托 planImageStudio(经 image-tools 插件 image.studio.plan),ResolveImageStudioTerminalStatus 依计数/取消决定终态。属 image-tools 领域类型定义,业务校验在插件。静态阅读,未执行构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "Consts L12-L23; status enums L32-L61; ImageStudioJob L105-L126 (UserID/Prompt json:\"-\" L107,L111); ImageStudioArtifact.StorageKey json:\"-\" L156; ImageStudioRepository L217-L236", - "ValidateImageStudioCreateInput L238-L241 -> planImageStudio (plugin_image_tools.go:80, plugin op image.studio.plan); ResolveImageStudioTerminalStatus L243-L257", - "File statically reviewed only; no build run." - ] - }, - { - "path": "backend/internal/service/image_studio_job_service.go", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "aec4e3d6f30957bf554bc702a9733fd59aa1f5baa80bf203816ea5c04f8a1c2f", - "review_fingerprint": "aec4e3d6f30957bf554bc702a9733fd59aa1f5baa80bf203816ea5c04f8a1c2f", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "下游新增 Image Studio 用户侧服务:EligibleKeys 只返回属于该用户、活跃未过期未耗尽、且绑定 canonical Cindy 图片分组(平台 cindy/线协议 openai/laxa-v1/AllowImageGeneration)并至少有一台兼容可调度 Cindy 账号的 Key,能力列表来自插件 image.studio.models;Create 经插件 image.studio.plan 归一化、要求模型为已知公开 Cindy 图片能力、校验 Key 资格、惰性启动运行时、保存参考/掩码失败即回滚、落库;Get/List/Cancel/Retry/OpenArtifact 均按 userID 作用域,OpenArtifact 校验过期。DTO 不含 API Key 明文。属 image-tools 领域业务编排(资格判定依赖核心 cindy 身份规则)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "EligibleKeys L62-L117 (UserID check L83, group identity L119-L123, account compatibility L96-L103); imageStudioModelCapabilities L125-L141 -> plugin op image.studio.models; eligibleAPIKey L143-L166", - "Create L168-L231 (planImageStudio L175 -> image.studio.plan; removeSaved L202-L206,L217,L227); Retry L253-L270; OpenArtifact L272-L288; handler image_studio_job_handler.go, routes/user.go:101-117", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/image_studio_job_service_test.go", - "candidate_owner": "image-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1f5450a59156c381de94eb069c5f7158fffd40e36955534156fcc6039ffe8239", - "review_fingerprint": "1f5450a59156c381de94eb069c5f7158fffd40e36955534156fcc6039ffe8239", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "新增单元测试(unit tag):EligibleKeys 过滤掉非 Cindy 的 legacy 分组 Key,且在永久免费 Cindy 目录没有图片模型时返回空,序列化结果绝不包含 API Key 明文、上游密钥或 key 字段;开启 imageStudio 灰度后 Create 对已下线的付费 Cindy 图片模型(gemini-3-pro-image)以 model_unavailable 拒绝,仓储未创建、存储未保存。证明 image-tools 服务在宿主内的资格与脱敏规则。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestImageStudioEligibleKeysHidesUnavailableCindyImageCandidatesAndCredentials L90-L110 (asserts NotContains must-never-leave-server / upstream-secret / \"key\"); TestImageStudioCreateRejectsRemovedPaidCindyImageModel L112-L136 (repo.created empty, store.saved empty)", - "Fakes L16-L74; canonicalImageStudioFixture L76-L88 builds canonical Cindy group/key/account", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/image_studio_job_test.go", - "candidate_owner": "image-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2406c6d8f0f06908bff8aa863add4548b5330dc0c4de09bb9d053ecd0c3728a4", - "review_fingerprint": "2406c6d8f0f06908bff8aa863add4548b5330dc0c4de09bb9d053ecd0c3728a4", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "新增单元测试(unit tag):ValidateImageStudioCreateInput(经插件 plan)对固定模型集与单图扇出的校验表——gpt-image-2 生成 4 张通过、gemini-3-pro-image 编辑接受参考+掩码、gpt 编辑 unsupported_mode、gemini 编辑缺参考 reference_required、生成模式带掩码 mask_not_allowed、张数>4 invalid_count、未知模型 unsupported_model;ResolveImageStudioTerminalStatus 依计数与取消标志给出 succeeded/partially_succeeded/failed/canceled/canceled_with_results。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestValidateImageStudioCreateInputEnforcesFixedModelsAndNativeOneFanout L11-L91 (7 cases with expected ImageStudioError codes); TestResolveImageStudioTerminalStatusPreservesPartialAndCanceledResults L93-L111", - "Subject functions image_studio_job.go:238-257; validation itself routed to plugin op image.studio.plan via planImageStudio", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/image_studio_runtime.go", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "956bac4467f5c9e3756e63a55c9f59fb0b1d87f22398ac408e5cef63ea8a3863", - "review_fingerprint": "956bac4467f5c9e3756e63a55c9f59fb0b1d87f22398ac408e5cef63ea8a3863", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "下游新增 Image Studio 专用后台运行时:选项归一(1..4 个 worker、250ms 轮询、10m 清理);Start 在互斥下幂等地先恢复被中断任务再启动 worker 与清理循环,Stop 取消并等待;worker 轮询 ClaimNext;processClaim 绑定插件策略上下文(image.studio.plan,插件停用即取消执行)、检查特性可用与 Key 资格、读取输入(缺失→input_expired)、执行、保存输出、CompleteSuccess 失败时删文件,failClaim 用 WithoutCancel 落库并只暴露安全错误码;cleanup 受 ImageStudioFeatureEnabled 门控(停用期间不清理过期文件)。这是与通用扩展任务宿主并列的 image-tools 领域专用运行时,执行器由 handler.ImageStudioGatewayExecutor 提供。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "normalized L19-L30; Start L61-L96 (RecoverInterrupted L70); Stop L98-L121; worker L123-L140; processClaim L153-L210 (bindProcessExtensionContext L158, EnsureImageStudioAvailable L165, eligibleAPIKey L169, output save/complete L198-L209); failClaim L212-L219; cleanup L246-L262", - "Wired by handler/wire.go:334-342 ProvideImageStudioRuntime with *ImageStudioGatewayExecutor; runtime lazily started from ImageStudioService.Create/Retry", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/image_studio_runtime_test.go", - "candidate_owner": "image-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "309a941d05938c22f349aecb8bc24c6c73898f4bc3473ecbe3aaa785269c34d9", - "review_fingerprint": "309a941d05938c22f349aecb8bc24c6c73898f4bc3473ecbe3aaa785269c34d9", - "review_status": "reviewed", - "decision": "plugin", - "owner": "image-tools", - "reason": "新增单元测试(unit tag):插件停用(pluginRuntime.beginDrain)会取消正在执行的宿主图片调用,条目记为失败、无成功、已保存输入不被删除,且后续 claim 直接失败不再发起上游 IO;运行时启动时恰好恢复一次被中断任务、8 个 claim 下并发执行上限为 4、释放后全部完成、Stop 在超时内返回。证明 image-tools 运行时的取消传播与并发上限。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestImageStudioDisableCancelsHostExecutionAndKeepsSavedInputs L34-L70 (failed==1, completed==0, store.removed empty, active==0); TestImageStudioRuntimeRecoversInterruptedAndCapsGlobalExecutionAtFour L139-L185 (max==4, recovered==1)", - "Fakes: imageStudioRuntimeRepoFake L17-L23,L72-L109; imageStudioBoundPolicy L25-L32; blockingImageStudioExecutor L111-L137", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/kimi_anthropic_usage_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cb2880ef019172f4b62cebf1e055464fc3ec82312a0cabf1e6b7f1433239bf5d", - "review_fingerprint": "cb2880ef019172f4b62cebf1e055464fc3ec82312a0cabf1e6b7f1433239bf5d", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "国产厂商(Kimi/GLM/DeepSeek)经 Anthropic 协议返回的 usage 别名归一化测试:prompt_tokens/cached_tokens、prompt_tokens_details.cached_tokens、prompt_cache_hit/miss_tokens 归一到 input 与 cache_read 桶,claudeUsageToOpenAIUsage 还原为包含式总量,且未缓存输入必须计费。下游相对上游仅在最后一个用例把期望单价改为 applyDeepseekTimePricing(pricing, timezone.Now()),因为下游 CalculateCost(billing_service.go:1346/1600,来自 4167b92de #171)按 DeepSeek 官方分时价冻结定价;该断言据此证明计费路径与分时价卡一致,其余断言与上游相同。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L252 to EOF; git diff aea725f = +4 lines (timezone import L9; L246-L248 applyDeepseekTimePricing(pricing, timezone.Now()) before the InDelta on cost.InputCost).", - "applyDeepseekTimePricing is downstream-only (deepseek_pricing.go:195, absent from aea725f; git log -S → 4167b92de) and is applied by BillingService at billing_service.go:1346/1600; subjects parseSSEUsagePassthrough / parseClaudeUsageFromResponseBody / mergeAnthropicUsage / claudeUsageToOpenAIUsage are core protocol usage parsing.", - "Not claimed: the DeepSeek time-pricing table and identity registry (deepseek_pricing.go) are outside this slice and were not reviewed; no test execution." - ] - }, - { - "path": "backend/internal/service/model_context_capacity.go", - "candidate_owner": "model-policy", - "role": "source", - "present": true, - "content_sha256": "81df735b05f1fb7d5b6bd487c15a0b315f7f37c03de7bf2329615f33e0fb8e3f", - "review_fingerprint": "81df735b05f1fb7d5b6bd487c15a0b315f7f37c03de7bf2329615f33e0fb8e3f", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "Full-file review; only the account-ID fact projection changed. Host custom precedence, observed-source identity and native planning projection remain host-owned.", - "evidence": [ - "Read all 654 lines. NewAccountModelContextCapacityResolver decodes account snapshots/overrides once, accepts a call-local live observation, and never writes catalog results into account state or the upstream observation cache.", - "Custom overrides remain highest priority. Vendor endpoints remain official-before-upstream; third-party relays remain upstream-before-official; the explicit default is source=default/no_verified_capacity, not a hidden static catalog fallback.", - "Independent input/output limits are taken only when valid and compatible with the planning window, never synthesized from the default. Protected OAuth/Cindy accounts retain their dedicated native/live metadata path.", - "Observed snapshots are bound to canonical endpoint/product/protocol/mode identity; keys, network proxies and public model aliases are intentionally excluded. Changing actual source identity prevents stale observations being relabeled as current.", - "LookupOfficialModelContextCapacity now includes account.ID. It still sends only bounded candidate/platform/type/mode/URL-component facts (not credentials). Matching-only namespace/spelling/finite effort variants never rewrite actual request IDs, overrides or observation keys.", - "Only one projection line changed; source ordering, alias identity storage, override mutation semantics and account-row aggregation are untouched." - ] - }, - { - "path": "backend/internal/service/model_context_capacity_catalog.go", - "candidate_owner": "model-policy", - "role": "source", - "present": true, - "content_sha256": "2d23b1c7af03a6af755752455a35de1cc0240ae7e6233fd61bca9bc65a097a1d", - "review_fingerprint": "2d23b1c7af03a6af755752455a35de1cc0240ae7e6233fd61bca9bc65a097a1d", - "review_status": "pending" - }, - { - "path": "backend/internal/service/model_context_capacity_catalog_test.go", - "candidate_owner": "model-policy", - "role": "test-or-fixture", - "present": true, - "content_sha256": "179befbfb5c1c083e2f26d8045a6f500ddc4bee2270d5974e72bd24c42636f28", - "review_fingerprint": "179befbfb5c1c083e2f26d8045a6f500ddc4bee2270d5974e72bd24c42636f28", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "model-policy", - "reason": "Full-file static test review: the existing table-integrity/provider-semantic checks are preserved, not rerun as part of this narrow fix.", - "evidence": [ - "Read the complete file. Integrity checks require nonempty exact IDs/metadata, valid dates and capacity bases, official HTTPS source hosts, pinned Codex references, unique provider/product/ID-or-alias tuples and exactly the expected ten providers.", - "Provider-semantic cases preserve Gemini input-only limits, MiniMax case/unknown independent limits, exact Qwen/Doubao hosted scopes, separate Kimi Coding k3 and explicit normalization disclosures.", - "Representative-value cases exclude unverified/retired identities such as deepseek-chat/reasoner and k3[1m]; they do not infer new rolling aliases or dates.", - "Current SHA matches the prior review. No representative values, catalog data or this test were changed or rerun." - ] - }, - { - "path": "backend/internal/service/model_context_capacity_catalog_test_fixture_test.go", - "candidate_owner": "model-policy", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b668e1aabc1280d768e32a5130278672d0f5f77d91276f1ab4c022553e296585", - "review_fingerprint": "b668e1aabc1280d768e32a5130278672d0f5f77d91276f1ab4c022553e296585", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Full-file review: this test-only fixture imports the independent catalog snapshot, so host tests do not maintain a duplicate production table.", - "evidence": [ - "Read all 13 lines. The _test.go suffix confines catalog.New()/Snapshot initialization and pinned-reference aliases to tests.", - "Production source search found no modelpolicy/catalog import or officialModelContextCapacityCatalog definition in backend/internal/service outside test files.", - "The fixture was not modified or separately rerun." - ] - }, - { - "path": "backend/internal/service/model_context_capacity_parser.go", - "candidate_owner": "model-policy", - "role": "source", - "present": true, - "content_sha256": "d8df4c1e93775b3726d51fb187bc97b3cc6f9745dfb87a947b38af607ea8fe50", - "review_fingerprint": "d8df4c1e93775b3726d51fb187bc97b3cc6f9745dfb87a947b38af607ea8fe50", - "review_status": "reviewed", - "decision": "plugin", - "owner": "model-policy", - "reason": "下游新增上游模型目录容量解析:parsePositiveSafeModelContextTokens 只接受 JSON 数字(≤128 字节、首字符数字、指数有界、big.Rat 精确整数、安全整数范围);ParseUpstreamModelContextCapacity 按字段宽容提取 context_window/max_context_window/max_input|output_tokens 的多种拼写与 limit.{context,input,output},仅 Anthropic 把 max_tokens 视为输出上限,推断 capacity_basis;ParseUpstreamModelContextCapacities 复用模型同步的协议 ID 选择器(Grok 特殊)、跳过无限制条目、重复 ID 按各字段最小值合并。属 model-policy 容量特性的数据解析层,被 group_model_capacity.bindLiveSource 等使用。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "parsePositiveSafeModelContextTokens L13-L35; ParseUpstreamModelContextCapacity L40-L90 (Anthropic-only max_tokens L73-L75, basis inference L79-L88); ParseUpstreamModelContextCapacities L95-L126; mergeDuplicateModelContextCapacity L128-L143", - "Caller: group_model_capacity.go:165 bindLiveSource; ID selection shared with upstream model sync (upstreamModelEntryID/grokUpstreamModelEntryID)", - "File statically reviewed only; no test/build run." - ] - }, - { - "path": "backend/internal/service/model_context_capacity_reference_test.go", - "candidate_owner": "model-policy", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c4339f66b12541d16576dcbd9663aad0e63448f7ed6c2281ea194b70adb1f4f1", - "review_fingerprint": "c4339f66b12541d16576dcbd9663aad0e63448f7ed6c2281ea194b70adb1f4f1", - "review_status": "reviewed", - "decision": "plugin", - "owner": "model-policy", - "reason": "新增测试:官方 GPT 参考容量查询——命名空间/拼写/effort 后缀变体映射到 canonical 条目并给出参考窗口(如 gpt-6-astra 1050000、gpt-5.5 272000),日期后缀与未知模型回落 default,返回的参考证据不可反向修改目录,product/conditions 字段存在;参考匹配保留原始键(raw 覆盖与裸 ID 覆盖不互借、第三方主机自报优先于官方参考、账号 JSON 不被改动);候选最小值与线上身份(GPT 形似别名不识别未知实际目标,候选池变化改变 ETag,非容量字段与输入体不变)。依赖 model-policy 插件目录经 lookupExtensionCatalog 可达。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S24-svc-admin-settings-ops-1-review.json", - "TestModelContextCapacitySelectedGPTReferenceAndExactVariants L11-L62 (20-row table, immutability L57-L58, product fields L55,L60-L61); ...ReferenceMatchingKeepsRawKeys L64-L94; ...ReferenceCandidateMinimumAndWireIdentity L96-L128", - "Subjects ResolveAccountModelContextCapacity / LookupOfficialModelContextCapacity (model_context_capacity.go:476-494) and group_model_capacity catalog.resolve/projectModelCapacityEnvelope", - "Test source read statically, not executed." - ] - }, - { - "path": "backend/internal/service/model_context_capacity_test.go", - "candidate_owner": "model-policy", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5beb4a200d9f2e4d943e3bfd502156860bcef66be2be9dc887b0cb0b2bbc8856", - "review_fingerprint": "5beb4a200d9f2e4d943e3bfd502156860bcef66be2be9dc887b0cb0b2bbc8856", - "review_status": "reviewed", - "decision": "plugin", - "owner": "model-policy", - "reason": "新增文件,model-policy 领域的容量解析单测。断言 ResolveModelContextCapacity 的优先级(custom>official>upstream>default)与独立上限、ParseUpstream* 解析器的安全数值/字段容错、ValidateModelContextOverrides 校验、CanManageModelContextCapacity 的托管厂商边界、以及 ModelContextCapacitySourceIdentity 的上游身份绑定(凭据轮换/URL 归一化不失效、真实上游变更则失效)。被测主体是 model-policy 业务(账号容量覆盖),与 plugins/model-policy 的官方 catalog 互补而非重复执行体。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S25-svc-admin-settings-ops-2-review.json", - "New file (ls-tree aea725f empty). Tests reference symbols in model_context_capacity.go / _parser.go (other slice): ResolveModelContextCapacity, ParseUpstreamModelContextCapacit(y|ies), CanManageModelContextCapacity, ModelContextCapacitySourceIdentity.", - "Proves capacity priority, parser tolerance, override validation, managed-provider gating, upstream-identity binding; does not execute or hit network.", - "Owner is model-policy plugin domain; plugins/model-policy/catalog owns the official catalog, this exercises account-level resolution." - ] - }, - { - "path": "backend/internal/service/model_context_identity.go", - "candidate_owner": "model-policy", - "role": "source", - "present": true, - "content_sha256": "8bf6848ee0d126a2b05749dfba1003bc1c442f05dceba838024eb6f7968a36d9", - "review_fingerprint": "8bf6848ee0d126a2b05749dfba1003bc1c442f05dceba838024eb6f7968a36d9", - "review_status": "reviewed", - "decision": "plugin", - "owner": "model-policy", - "reason": "新增文件,account 级模型上下文容量覆盖的身份归一化。capacityCanonicalUpstreamID 把上游目标(仅 OpenAI ApiKey 且可管理时经 resolveOpenAIModelReasoningAlias)规范化且拒绝公共路由别名二次映射;capacityOverrideTargetResolver/resolveCapacityOverrides/capacitySnapshotTargets 处理旧别名写入、精确键优先与冲突剔除;ApplyAccountModelContextOverrides 做补丁内冲突校验并清除过时拼写键。属 model-policy 业务规则,物理驻留 core/service,被 repository/account_repo.go:860 调用。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review; new file (ls-tree aea725f empty).", - "Functions: capacityCanonicalUpstreamID (L8-18), capacityOverrideTargetResolver (L22-38), resolveCapacityOverrides (L40-60), capacitySnapshotTargets (L62-88), ApplyAccountModelContextOverrides (L92-116).", - "Caller: backend/internal/repository/account_repo.go:860 service.ApplyAccountModelContextOverrides. Map-iteration nondeterminism is neutralized by exact-target precedence; no unbounded maps, no secrets.", - "Not a duplicate executor: plugins/model-policy/catalog holds the official reference catalog, this file holds per-account override identity resolution." - ] - }, - { - "path": "backend/internal/service/model_context_identity_test.go", - "candidate_owner": "model-policy", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7e69bcc4de246fb5723056bf2bca0eb3d6adab6cf2e7b3f29a5e7587331cdf39", - "review_fingerprint": "7e69bcc4de246fb5723056bf2bca0eb3d6adab6cf2e7b3f29a5e7587331cdf39", - "review_status": "reviewed", - "decision": "plugin", - "owner": "model-policy", - "reason": "新增文件,model_context_identity.go 的单测。断言前向目标+旧别名共享覆盖、别名冲突剔除、真实目标不被二次重映射(a->b->c 时 a 用 b 的值)、快照仅认可已识别拼写。被测主体为 model-policy 账号容量覆盖身份逻辑。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review; new file.", - "Tests: TestCapacityIdentityUsesForwardTargetAndLegacyOverrides, ...ConflictsAndExplicitEdit, ...DoesNotRemapRealTargetTwice, ...SnapshotUsesRecognizedSpellingOnly.", - "Uses helpers newGroupCapacityAccount (group_model_capacity_test.go) / newGroupModelCapacityCatalog (group_model_capacity.go).", - "Proves alias canonicalization + conflict handling in model_context_identity.go; not executed." - ] - }, - { - "path": "backend/internal/service/model_pricing_resolver.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9bcf3f881245ef05aed79d639f0f626a011b3cfd20aac9631ddf76b107cd6df4", - "review_fingerprint": "9bcf3f881245ef05aed79d639f0f626a011b3cfd20aac9631ddf76b107cd6df4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "统一模型定价解析器:Group 价卡 → 渠道定价(字面名/归一化名)→ LiteLLM → fallback,以及区间/按次/图片层级与渠道覆盖的合成。下游相对上游 46 行:新增 PricingSourceCindyCatalog,严格 Cindy 分组(Platform=cindy、wire=openai、profile=cindy-laxa-v1)直接返回无 BasePricing 的 cindy_catalog 结果而不落入渠道/LiteLLM 定价,通用 token 计费随后因 GetIntervalPricing 为 nil 报 ErrModelPricingUnavailable(billing_service.go:1332-1335),实际 Cindy 定价由 OpenAI 用量路径按请求期快照计算(shouldUseCindyTextPricingContext / calculateCindyCatalogTextCost),core 未复制 Cindy 价目;Group 与渠道定价匹配增加 deepseekPricingAliases 同身份别名回退,DeepSeek 身份匹配为 fallback 时定价来源标记为 fallback(4167b92de #171 的核心正确性修正)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L436 to EOF in two chunks; git diff aea725f hunks: consts L10-L16, Resolve L74-L86 (Cindy fail-closed), matchGroupModelPricing/Literal L160-L193, resolveBasePricing L203-L205, lookupChannelPricingNormalized L226-L230.", - "Consumers: PricingSourceCindyCatalog is referenced only here and in model_pricing_resolver_test.go:74; billing_service.go:1345 applies DeepSeek time pricing only for non-group/channel sources; gateway_usage_billing.go:1030 and openai_gateway_usage.go:1137 treat only group/channel as channel pricing, so a cindy_catalog result never becomes a channel price.", - "Cindy pricing ownership: openai_gateway_usage.go:803-837 gates on the account + cindyPricingSnapshotFromContext (request-scoped snapshot from 63a98c8cc) and cindy_text_billing.go:13 calculateCindyCatalogTextCost computes from snapshot capabilities; deepseekPricingAliases (deepseek_pricing.go:61) is downstream-only and enumerates registry aliases for the same canonical DeepSeek identity.", - "Not claimed: the OpenAI usage path's behaviour when shouldFailClosedCindyTextPricing is true was not reviewed here (outside slice); no test execution." - ] - }, - { - "path": "backend/internal/service/model_pricing_resolver_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a3168d9fcc0eb08ea289816e6c08854ce443d11e7748066d3373ce3adc1ed406", - "review_fingerprint": "a3168d9fcc0eb08ea289816e6c08854ce443d11e7748066d3373ce3adc1ed406", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "ModelPricingResolver 单元测试:无分组/未知模型的 litellm/fallback 来源、区间定价匹配与回退、按次与图片层级、渠道 token/按次/图片覆盖、缓存构建失败时的降级、ImageOutputPriceExplicit 标记、渠道覆盖不得污染共享 fallbackPrices、Group 价卡优先于渠道且长上下文只用官方阶梯、连续媒体单位计费。下游相对上游仅新增 TestResolve_StrictCindyNeverFallsThroughGenericPricing:即使 fallbackPrices 里存在该模型价,严格 Cindy 分组也必须解析为 Source=cindy_catalog 且 BasePricing 为 nil,证明下游 Resolve 的 Cindy 失败关闭分支不会落入通用定价;其余用例与上游一致。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L926 to EOF in four chunks; git diff aea725f = +18 lines (new test at L60-L76), all other tests unchanged.", - "The new test exercises model_pricing_resolver.go L74-L86 (strict Cindy group: Platform=cindy, WirePlatform=openai, ProviderProfile=cindy-laxa-v1) and asserts PricingSourceCindyCatalog with nil BasePricing; it does not cover the DeepSeek alias paths (deepseekPricingAliases) added in the same downstream change.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/model_rate_limit.go", - "candidate_owner": "core-quota-and-protocol", - "role": "source", - "present": true, - "content_sha256": "c90fd189bcad2004c643d47a41ded0d9b97539691b5888944f154da5d7a4a82c", - "review_fingerprint": "c90fd189bcad2004c643d47a41ded0d9b97539691b5888944f154da5d7a4a82c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Model-scoped cooldown lookup derives the same mapped/forwarded model key used by scheduling, then appends only declared feature-family scopes; Spark cooldowns therefore remain model-scoped instead of account-global.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=c90fd189bcad2004c643d47a41ded0d9b97539691b5888944f154da5d7a4a82c; current_sha256=c90fd189bcad2004c643d47a41ded0d9b97539691b5888944f154da5d7a4a82c; inventory_sha256_match=true", - "lines 65-126: model key normalization and platform-specific scope expansion", - "lines 201-249: reset/reason lookup and active check", - "lines 252-272: model_rate_limits snapshot persistence", - "caller: backend/internal/service/gateway_scheduling.go:1166" - ] - }, - { - "path": "backend/internal/service/namespace_roundtrip_control_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d1abc0a4cdd4837f7d7aa4506e8701a4c10a05f8bab4381dcad63a0a0546d559", - "review_fingerprint": "d1abc0a4cdd4837f7d7aa4506e8701a4c10a05f8bab4381dcad63a0a0546d559", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增、带 reasoning_fidelity && namespace_roundtrip 构建标签的离线控制测试(package service_test),用假上游 namespaceOfflineUpstream 验证 Responses API 工具 namespace 往返实验的安全护栏:固定 run id/账号 16050/映射/账本 SHA 的 bootstrap 校验、null 与字符串 namespace 的无损回放(namespaceContinuation)、大整数不被四舍五入比较、Python broker 的 before_send/attempt_result 逐轮合同与累计配额、ultra→max 线上 effort 门与冻结分组策略拒绝、混合提示词必须使用已发布的 effective 正文、incomplete/未授权/线上体变更/槽位耗尽一律不发送、缺 namespace 时停止不做替换链。这是实验治理的测试脚手架,不证明任何生产修复;默认构建不编译。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L447 to EOF in two chunks; git ls-tree aea725f prints nothing → new downstream file, whole file is the delta.", - "Depends on sibling harness code in namespace_roundtrip_live_test.go (namespaceHarness, namespaceBudgetUpstream, namespaceValidateBootstrap, namespaceContinuation) and service.ReasoningFidelityGatewayForTest; bootstrap fixture uses a relay OpenAI API-key account (ID 16050, base_url upstream.invalid) with fixed model_mapping gpt-6-astra→gpt-6-astra-ssvip / gpt-5.6-luna.", - "Assertions also cover leak checks (api key, opaque reasoning, prompt body, upstream host never appear in broker output) and prompt-skills snapshot types (BusinessSystemPromptCompositionCodexSkillHybrid, RemoteSkillBundleVersion) used only as frozen fixtures.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/namespace_roundtrip_diagnostic_support_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bb3fcf64b3d11087670fdd274914463908fe71c5c0f347d62078c483e53e7431", - "review_fingerprint": "bb3fcf64b3d11087670fdd274914463908fe71c5c0f347d62078c483e53e7431", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增、带 reasoning_fidelity && namespace_roundtrip 构建标签的 package service 测试支撑文件:NamespaceRoundtripSafeErrorForTest 只是把生产侧 continuationDiagnosticError(上游错误体 → 结构化形状)与 sanitizeOpenAIContinuationDiagnostic(类型/代码/参数/提示白名单脱敏)串起来并投影为 error_type/error_code/error_param/hints/inspection_limited,供 service_test 包的 namespace 往返诊断测试使用;不能暴露原始错误文本,也不能扩大白名单。默认构建不编译,不证明生产修复。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L29 to EOF; git ls-tree aea725f prints nothing → new downstream file, whole file is the delta.", - "Wraps production OpenAI continuation diagnostic producer/sanitizer (continuationDiagnosticError, sanitizeOpenAIContinuationDiagnostic, OpenAIContinuationDiagnostic, openAIContinuationFingerprint) without adding logic beyond OR-ing the inspection_limited flag.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/namespace_roundtrip_diagnostic_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b099cbc13fe5d87b9fa78b4f0e0678fac0ab1351d2645c49c5186998f261228f", - "review_fingerprint": "b099cbc13fe5d87b9fa78b4f0e0678fac0ab1351d2645c49c5186998f261228f", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增、同构建标签的 service_test 测试:namespaceSafeErrorDetail 从有界响应捕获中挑选 JSON 或 SSE 的 response.failed/error/response.error 信封,再经 NamespaceRoundtripSafeErrorForTest 投影;断言白名单内的 type/code/param 与 hints 原样保留(含 SHA256/字节数指纹)、未知文本只留哈希绝不泄漏 private-error-secret、显式 null 与缺失字段不被发明、未终止/不相关/重复/超过 fidelityMaxBody 的捕获标记 inspection_limited、以及假上游返回失败时 harness 只发一个 POST 并输出安全 attempt_result。属实验治理脚手架,不证明生产修复;默认构建不编译。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L240 to EOF; git ls-tree aea725f prints nothing → new downstream file, whole file is the delta.", - "Uses harness helpers from namespace_roundtrip_control_test.go / namespace_roundtrip_live_test.go (namespaceOfflineUpstream, namespaceOfflineHarness, fidelityMaxBody, fidelitySSELine, fidelityJSONObject, fidelityHash) and the fixed pinned SHA256 for param input[11].namespace.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/namespace_roundtrip_live_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8abff07631c38f7264e8b283f8b239e8c88e02097c9a00cd5ab3cda53dac41ff", - "review_fingerprint": "8abff07631c38f7264e8b283f8b239e8c88e02097c9a00cd5ab3cda53dac41ff", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增、带 reasoning_fidelity && namespace_roundtrip 构建标签且需 SUB2API_NAMESPACE_ROUNDTRIP_LIVE=1、精确 -run 选择与 revision=3 才运行的受控线上实验:从 stdin 读取 broker 的 bootstrap(固定 run id、账本 SHA、固定账号 16050 与分组/用户/映射/冻结提示词),用 config.LoadForBootstrap 与真实 HTTPUpstream 组装 OpenAIGatewayService(ReasoningFidelityGatewayForTest),按 astra 三轮 + luna 两轮跑 Responses 工具 namespace 往返,每次真实发送都需 broker send_granted 且槽位一次性(namespaceBudgetUpstream 拦截重放/TLS 回退/兼容重试、校验端点/授权哈希/线上体合同),输出仅含枚举、数字与哈希的安全协议。这是实验脚手架而非产品行为的证明;默认构建不编译,本次仅静态阅读,未运行任何线上或离线路径。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L897 to EOF in three chunks; git ls-tree aea725f prints nothing → new downstream file, whole file is the delta.", - "Guards observed: namespaceLiveSelectionValid L207-L209, namespaceValidateBootstrap L288-L340 (fixed account/group/proxy/mapping/prompt, resume_not_allowed), namespaceBudgetUpstream.send L778-L867 (used-slot guard, source_changed hash check, grant protocol, redirect-disabled context, nil GetBody), validWireBody L869-L897 (max effort, no reasoning.mode, no previous_response_id/conversation/context_management).", - "Hygiene note (not a finding): the source embeds production identifiers (account ID 16050, name 白嫖-dmxapi, user 920000016050, ledger SHAs) as fixed-run constants; no credentials are embedded and broker output hashes the endpoint/authorization.", - "Helpers fidelity* (fidelityPrepareIngressBody, fidelityParseResponse, fidelityCaptureBody, fidelityHash) and ReasoningFidelity*ForTest hooks live in files outside this slice and were not reviewed here; no test execution." - ] - }, - { - "path": "backend/internal/service/oauth_refresh_api.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5f71bded81201fd1836ec56b3c0f79c197d02db2b63cc7482aa6c3de264756e7", - "review_fingerprint": "5f71bded81201fd1836ec56b3c0f79c197d02db2b63cc7482aa6c3de264756e7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "统一 OAuth 刷新入口 OAuthRefreshAPI.RefreshIfNeeded:进程内互斥 + 分布式锁、锁内 DB 重读与身份校验、请求路径失败关闭、invalid_grant 竞争恢复、Grok 成功刷新的凭据 CAS 与持久重读、_token_version 版本戳与凭据持久化,属宿主通用认证机制。下游相对上游仅 L228-L229:当 ctx 带 Codex 票据凭据准备标记(codex_ticket_manual.go 的 withCodexTicketCredentials,仅由 plugin_extension_accounts.go ResolveExtensionIdentity 在 query.PrepareCredentials 时设置)且账号满足 CodexTicketAccountEligible(OpenAI OAuth 类非影子账号)时,允许对 disabled/error 账号刷新令牌而不改动管理员的状态/可调度/错误信息,是为 codex-runtime 票据准备提供的宿主胶水;其他平台不受影响。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L468 to EOF in two chunks; git diff aea725f = 3 lines (L228-L229 ticketRefresh gate on the IsActive check).", - "Call chain: withCodexTicketCredentials/isCodexTicketCredentialContext (codex_ticket_manual.go:11/15, downstream-only, absent from aea725f); CodexTicketAccountEligible (codex_ticket_lifecycle.go:76 → isOpenAICodexTicketAccount); setter plugin_extension_accounts.go:58-59; the same ctx flag also stops openai_token_provider.go:165 from disabling an account with a missing refresh token during ticket preparation.", - "Proof in slice: oauth_refresh_api_test.go L211-L240 (inactive OpenAI account refreshed only under the ticket ctx, status/schedulable/error message preserved; Anthropic disabled account still not refreshed).", - "Not claimed: no runtime verification; the persisted credential write path (persistAccountCredentials / UpdateCredentials) is outside this slice." - ] - }, - { - "path": "backend/internal/service/oauth_refresh_api_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c8468fbc2c31f4b9a8066fd64e808d43a9f45cebce37b7c41113be8ddc7a2977", - "review_fingerprint": "c8468fbc2c31f4b9a8066fd64e808d43a9f45cebce37b7c41113be8ddc7a2977", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "OAuthRefreshAPI 单元测试:成功刷新与版本戳、锁被占/锁错误降级/无缓存、已刷新跳过、刷新错误与 DB 写失败、Grok 成功 CAS 让并发重授权获胜/持久化失败与持久重读失败视为提供方级隔离、DB 重读失败与请求路径失败关闭、执行器合同复核、本地锁遵守 ctx、父 ctx 取消后仍用清理 ctx 释放分布式锁、超时后的迟到凭据不落库、invalid_grant 竞争恢复、本地互斥串行化、MergeCredentials/BuildClaudeAccountCredentials、刷新策略常量。下游相对上游仅新增 TestRefreshIfNeeded_TicketPreparationAllowsInactiveOpenAIWithoutChangingStatus(L211-L240):disabled/error 的 OpenAI OAuth 账号在普通 ctx 下不刷新,在 withCodexTicketCredentials ctx 下刷新一次且状态/可调度/错误信息保持不变,而 Anthropic 账号不受票据 ctx 影响——这是对 codex-runtime 票据准备宿主胶水的桥接测试,其余用例为上游核心内容。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L1140 to EOF in four chunks; git diff aea725f = +31 lines (single new test at L211-L240), all other tests and mocks unchanged.", - "The new test drives oauth_refresh_api.go L228-L229 via withCodexTicketCredentials (codex_ticket_manual.go:11) and CodexTicketAccountEligible (codex_ticket_lifecycle.go:76); repo mock UpdateCredentials only replaces Credentials, so the status/schedulable/error-message assertions hold by construction of the mock plus the production code path never calling Update.", - "Not claimed: the plugin-side ticket preparation flow (ResolveExtensionIdentity, plugin_extension_accounts.go) is outside this slice; no test execution." - ] - }, - { - "path": "backend/internal/service/oauth_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9b282b1bfc34b2da8a9dfc93efa04ca439a06c0ff0c4eec3015b79ba900841f6", - "review_fingerprint": "9b282b1bfc34b2da8a9dfc93efa04ca439a06c0ff0c4eec3015b79ba900841f6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "Claude OAuth 服务(PKCE 授权 URL、setup-token 范围、授权码/Cookie sessionKey 换取令牌、org/account 信息提取、刷新与代理解析、会话存储清理)以及 OpenAI/Grok/Claude OAuth 客户端接口定义,属宿主通用认证机制。下游相对上游仅 +7 行:新增可选接口 OpenAIOAuthIdentityRefresher.RefreshTokenWithIdentity,让已有 OpenAI 账号用与推理一致的账号级 Codex 出站身份(User-Agent/originator)刷新令牌;由 repository/openai_oauth_service.go:92 实现、service/openai_oauth_service.go:226-231 在身份非空时经类型断言选用、否则回退 RefreshTokenWithClientID。这是为 codex-runtime 身份一致性提供的宿主侧端口声明,不含业务规则。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S22-svc-gateway-billing-2-review.json", - "Read L1-L333 to EOF in two chunks; git diff aea725f = +7 lines (interface OpenAIOAuthIdentityRefresher at L21-L26).", - "Call chain: OpenAIOAuthService.refreshTokenWithIdentity (openai_oauth_service.go:223-231) type-asserts the client to OpenAIOAuthIdentityRefresher; production implementation repository/openai_oauth_service.go:92; symbol absent from aea725f.", - "Claude OAuth logic (OAuthService methods L52-L333) is unchanged from upstream; log.Printf lines only announce field presence, no secrets logged.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/oauth_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9b67c9f17f6d9bd6124e58e5c4c2b82ca919e3b8273aa0de821b93b230408556", - "review_fingerprint": "9b67c9f17f6d9bd6124e58e5c4c2b82ca919e3b8273aa0de821b93b230408556", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "OAuthService(Claude 账号 OAuth:生成授权/SetupToken URL、换码、刷新令牌)的单元测试,断言 sessionStore 生命周期(成功换码后删除 session)、scope 区分(oauth vs inference)、token 字段映射、代理 URL 拼装(http 与 socks5://user:pass@host:port)与 Stop 幂等。下游相对上游 aea725f 仅在 6 处 t.Fatal 后补 return(静态检查空指针防护),无任何行为性改动;被测对象是宿主账号凭据机制,与插件业务无关。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "626 行全读:mockClaudeOAuthClient(L17-L50) 与 mockProxyRepoForOAuth(L54-L112) 桩 + 15 个用例,锚点 TestOAuthService_ExchangeCode_Success(L246)、RefreshAccountToken_WithProxy(L535,断言 socks5://user:pass@socks.example.com:1080)、ExchangeCode_NilOrg(L583)、Stop_NoPanic(L618)。", - "git diff aea725f: 仅 +6 行 return,位于 TestNewOAuthService/GenerateAuthURL/GenerateSetupTokenURL/ExchangeCode_SessionNotFound/ExchangeCode_ClientError/RefreshAccountToken_NoRefreshToken 的 t.Fatal 之后;不证明任何生产行为修复。", - "No production behavior edit or test execution; assertions were read statically only." - ] - }, - { - "path": "backend/internal/service/openai_account_model_transient.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "4dbbe3b24bde4a62dd3d789c61c92c128f1019f4e490aa272c97739401983d8d", - "review_fingerprint": "4dbbe3b24bde4a62dd3d789c61c92c128f1019f4e490aa272c97739401983d8d", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 账号×模型级瞬时故障熔断状态(按 (AccountID, 小写模型名) 键控,连败 2 次 10s、3 次起 45s 冷却,30 分钟 streak TTL,最多 4096 条 LRU 淘汰)。下游相对上游:recordSuccess 改为返回 bool,且在冷却仍生效时拒绝清除(迟到的成功不再抹掉活动冷却);新增 recordOfficialSuccess 供显式标记的普通 HTTP 路径按上游语义无条件清除;新增 clearAccount 按账号清除全部模型条目;新增 block 以显式冷却时长直接进入 ≥2 连败并单调延长 blockUntil。键含实际 AccountID,容量有界。属于核心调度运行态的正确性修正;静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (70 lines): recordSuccess L131-L143 (returns false while time.Now().Before(entry.blockUntil)), recordOfficialSuccess L147-L155, clearAccount L157-L168, block L170-L207 (streak floor 2, blockUntil = max(existing, now+cooldown)).", - "Unchanged: key normalization L63-L77 (accountID>0, model <=512 bytes), recordFailure L79-L129, isBlocked L209-L231, evictOldestLocked L242-L259 bounding the map at maxEntries.", - "Consumers verified in same slice: openai_account_runtime_transient_test.go asserts the late-success behavior. No production behavior edit or test execution." - ] - }, - { - "path": "backend/internal/service/openai_account_runtime_block_fastpath.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "bb0ff531468bdb456ce7586df9893356b0874aed41c0f371e3635fab088d0d15", - "review_fingerprint": "bb0ff531468bdb456ce7586df9893356b0874aed41c0f371e3635fab088d0d15", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 协议族账号的运行时阻断快路径:上游错误分类入口 handleOpenAIAccountUpstreamError(先请求级安全/预算/容量分流,再 Cindy 健康信号、访问态 401/403、模型 not-found/临时停调隔离、429 分类与瞬时冷却)、进程内账号级阻断(per-account 互斥锁 + generation CAS,independent 与 persisted DB 镜像双来源,effectiveUntil 取并集且清除只回收本来源)、Cindy 健康/余额终态阻断(零截止时间,按 CindyCredentialGeneration+凭据指纹绑定,ABA 换代自动失效)、OAuth 跨副本 Redis 半开熔断(owner 声明/续租 lease/选中晋升/未选中释放)、严格续链门 isOpenAIAccountStrictContinuationBlockedContext(有限冷却放行绑定账号、终态仍 fail-closed)、CooldownOpenAIRetryExhausted 与 429 storm 计数。Codex 票据门只经 openAICodexTicketBlocksAccount→pluginManager.SchedulingDecision 适配到 codex-runtime 插件,本文件无第二套票据生命周期实现。所有状态键为实际 account.ID(模型维度另加小写模型名与 owner)。本条按协调者指示评审 Codex 冻结提交 63a98c8cc 之后的当前字节(自算 sha bb0ff531…,与切片记录的 c7ebafbb… 不同);上游 612 行→当前 1878 行,增量约 1510 行为上述下游新机制。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json; reviewed bytes sha256 bb0ff531468bdb456ce7586df9893356b0874aed41c0f371e3635fab088d0d15 (frozen version after commit 63a98c8cc; slice sha c7ebafbb... is stale by instruction).", - "Delta vs aea725f (612 -> 1878 lines) anchors: probe context/lease L32-L323 (withOpenAIRuntimeBreakerProbeOwner, attachSelectionRuntimeBreakerProbe returns nil and releases the slot when lease promotion fails L189-L209, renewal goroutine stops on stop/ctx.Done L270-L285), reacquire for same-account retry L325-L404, handleOpenAIAccountUpstreamError L452-L605 (transient model cooldown only for OpenAI APIKey and not pool-mode-retryable L586-L603), handleCindyBalanceTerminalEvent L609-L626, BlockAccountSchedulingFromPersistedCooldown L755-L761 (Cindy runtime-compatible accounts excluded from DB-mirror semantics), block sources model L1173-L1265 (independent owner takeover comment L1256-L1258), Cindy episode blocks L788-L866 and generation/fingerprint validation L1343-L1382, strict continuation gate L1690-L1719, CooldownOpenAIRetryExhausted L1724-L1825, 429 storm L1827-L1878.", - "Ownership boundary: ticket gate delegates via openAICodexTicketBlocksAccount (service/codex_ticket_plugin.go L66-L68 pluginManager.SchedulingDecision; harvest/stop via InvokeAdminExtension L70-L113) — adapter to the codex-runtime plugin, no second ticket lifecycle here. Cindy identity/fingerprint reuse cindy_identity.go and AccountCredentialFingerprint; hasCanonicalCindyProviderIdentity from provider_identity.go L107.", - "Identity binding checks: every map (openaiAccountRuntimeBlockUntil/Sources/Generation, cindyHealthRuntimeBlocks, cindyBalanceRuntimeBlockFingerprint, openaiOAuth429RetryStartedAt) is keyed by account.ID; Redis breaker keys add normalized model and owner string; spark shadows are excluded from OAuth-429 runtime blocking and storm counting (L643-L647). Redis read failures fail open for the single-probe path (logged, L1669-L1672) and fail closed for Cindy terminal pending reads (L903-L906) — both deliberate per comments. No secrets in logs (account_id/model/reason only).", - "Statically reviewed only; no test execution, no runtime verification of the Redis lease protocol." - ] - }, - { - "path": "backend/internal/service/openai_account_runtime_block_fastpath_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "11d20fe9ba3f5af446a7923c32de603873bae4a937b829c41b2fe127f2366477", - "review_fingerprint": "11d20fe9ba3f5af446a7923c32de603873bae4a937b829c41b2fe127f2366477", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "fastpath 运行时阻断的单元测试(//go:build unit,上游 851 行→1883 行)。以内存版 Redis breaker 存根(按 accountID+小写模型键、owner 独占半开)断言下游新机制的关键行为:lease 晋升失败必须返回 nil 选择、释放槽位并清空全部 claim;并发 Clear/Block 经 per-account 锁串行化,新阻断不被并发清除吞掉;熔断跨服务实例生效,半开探测 owner 独占且 allowed 判定后仍复查 Redis,模型 scope 被拒时原子回滚账号 scope claim;严格续链(OpenAI 与 Cindy)失败时报 IsOpenAIContinuationStateUnavailable 且不切换账号、保留 response 绑定,Cindy 有限冷却仍放行绑定账号而零截止终态阻断;APIKey 路径不使用 Redis 半开;同账号重试转移探测所有权直到最终失败且恰好释放一次(幂等);成功只清除本次 claim 的确切 scope,迟到成功不清除仍生效冷却;429 快路径跳过 spark 影子、fallback 关闭时不产生冷却、未耗尽配额头不阻断;池模式可重试状态码不建模型瞬时冷却而非可重试 5xx 仍建;model-not-found/临时停调按 (账号,模型) 经 SetModelRateLimit 隔离,未知模型保留账号级兜底;Cindy banned 阻断无限期且按 generation+指纹 ABA 界定,凭据轮换使旧余额指纹失效;persisted 镜像与 independent 来源互不越权(清除不复活、DB 镜像不延长 Redis、回滚只撤自己的贡献);429 storm 门控与 Grok 一次跟进预算。证明 fastpath 下游修正;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f is ~1786 changed lines (851 -> 1883). Key tests: stub store L19-L207, failed promotion L118-L146, concurrent clear/block L209-L261, cross-instance + owner-exclusive half-open L263-L330, atomic claim rollback L332-L355, strict continuation OpenAI/Cindy/missing-binding L357-L543, APIKey ignores Redis probe L545-L662, probe transfer and idempotent release L664-L840, claim release on selection outcome L842-L996, late success L998-L1031, 429 fast path incl. spark shadow L1033-L1147, pool-mode vs non-retryable transient L1184-L1264/L1428-L1480, retry-exhausted scopes L1266-L1426, model isolation vs unknown-model account block L1482-L1589, Cindy ABA generation scope L1617-L1646, sources model no-resurrection/no-extension/owned-rollback L1648-L1836, 429 storm L1838-L1883.", - "Subjects are the same-slice fastpath file and openai_account_scheduler.go selection sites; Cindy episode fixtures reuse AccountCredentialFingerprint with the exact laxarouter root.", - "Statically read only; assertions described, not executed." - ] - }, - { - "path": "backend/internal/service/openai_account_runtime_transient_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bc482f1cfa7260862fff15da3a17c1e1589aeb326fe5728bf3f615ae72633896", - "review_fingerprint": "bc482f1cfa7260862fff15da3a17c1e1589aeb326fe5728bf3f615ae72633896", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 瞬时上游错误处理的测试。下游相对上游:ReportOpenAIAccountScheduleResult 改为以 account.ID(int64)而非 *Account 上报,并新增断言迟到的成功不清除仍在生效的模型冷却、把 blockUntil 人工置为过去后成功才清除;HardDisableStillBlocksWholeAccount 改为 PersistedCooldownClearsWithDatabaseState:BlockAccountSchedulingFromPersistedCooldown 设置的账号级阻断在首次 isOpenAIAccountRuntimeBlocked 命中后,isOpenAIAccountRequestRuntimeBlocked(…, false) 与再次查询均为 false(运行时阻断随数据库状态清除)。其余上游用例断言 5xx/52x 只阻断请求的模型不阻断整个账号、529 只算过载、参数类 400 不阻断。证明 openai_account_model_transient.go 与 fastpath 的下游修正;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (21 lines): L88-L100 (ReportOpenAIAccountScheduleResult(account.ID, ...), late success keeps block, manual blockUntil expiry then clears), L119-L129 (BlockAccountSchedulingFromPersistedCooldown + 3-arg isOpenAIAccountRequestRuntimeBlocked).", - "Upstream tests read: L21-L38, L40-L60, L62-L64, L103-L117; stub repo L13-L19.", - "Statically read only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_account_scheduler.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f2d79edace853657c0361863563e31d9037dd6c51829388b1ca8dcc4bd651428", - "review_fingerprint": "f2d79edace853657c0361863563e31d9037dd6c51829388b1ca8dcc4bd651428", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 协议族账号调度器:四层选择(previous_response 续链、guardian parent、session sticky、加权负载均衡 TopK+加权洗牌+溢出回退)、EWMA 错误率/TTFT 运行统计、slot 获取与 DB recheck 预算、高级调度器 DB 设置缓存、评分快照与上游倍率因子。下游相对上游(560 行)新增:严格续链与可迁移续链分流(selectAccountByPreviousResponseIDForStrictContinuation vs WithPolicy,响应亲和扩展到 Cindy 平台);所有选中点包上 attachSelectionRuntimeBreakerProbe(半开 claim 晋升为请求持有 lease,未选中/未选出在 selectAccountWithScheduler 的 defer 统一释放);sticky 解绑改为 deleteStickySessionAccountIDIfMatches(按当时读到的 accountID 条件删除,防止误删并发新绑定);候选过滤用 isOpenAIAccountCandidateRuntimeBlockedContext(投影安全,票据等凭据绑定门推迟到 authoritative fresh/recheck,经 fastpath 的 openAICodexTicketBlocksAccount 适配 codex-runtime 插件,无第二套票据实现);openAIRequestedModelForAccount 按 Cindy 账号从 context 解析实际模型;Cindy 平台候选加 provider_identity_mismatch 门与按能力→CindyEndpoint 的目录门(含 images endpoint context);新增账号类型偏好选择(先排除他类型再可选回退);失败诊断带 rejected 原因计数与最短 retryAfterSeconds;ReportOpenAIAccountScheduleResult 改为 accountID+owner 作用域清除;upstream cost/legacy rate 门从 IsOpenAIOAuthLike 收紧为 IsOpenAIOAuth;quota headroom 按 primary/secondary 指针配对窗口,不跨窗口共享截止时间。宿主调度机制;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S15-svc-account-scheduler-1-review.json", - "Delta vs aea725f (560 lines) anchors: OpenAIAccountTypePreference L97-L103 and preference selection L2228-L2303, strict/movable continuation split in Select L406-L437 and selectAccountWithSchedulerOnce L2450-L2474, probe attachment at all selection sites (L612/L632/L1267/L1365/L1373/L1791) with releaseClaimsExcept defer L2354-L2363, deleteStickySessionAccountIDIfMatches L536/L1329/L1335, candidate vs authoritative gate L1523-L1530 and L1841-L1874 (isAccountRequestCompatibleReasonWithRuntimeGate), provider_identity_mismatch L1860-L1862, model_rate_limited per-model gate L1875-L1882, accountSupportsOpenAICapabilities Cindy endpoint mapping L2640-L2693, filterStats.failure with diagnostics/retryAfterSeconds L1393-L1424, reportOpenAIAccountScheduleResult owner-scoped clears L2792-L2802, IsOpenAIOAuth narrowing L3157/L3221/L3239, openAICanonicalQuotaWindows pointer-paired windows L3316-L3363.", - "Slice-specific checks: sticky/probe/runtime state all keyed by account.ID (+normalized model, owner); platform gate L1519 plus Cindy identity gate; quota headroom pairs each used% with its own window reset (no shared deadline); the Codex ticket gate is deferred to the authoritative account and implemented as a plugin adapter (fastpath L1602-L1608 -> codex_ticket_plugin.go SchedulingDecision), not re-implemented here.", - "Duplication note (not a finding): the strict-continuation branch exists both in scheduler.Select and selectAccountWithSchedulerOnce; the Once branch runs first and returns on success, the Select branch covers the advanced-scheduler path — a redundant second read at worst, no divergent semantics observed statically.", - "Statically read only; no test or build execution." - ] - }, - { - "path": "backend/internal/service/openai_account_scheduler_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0e777addc8ac6ac3994e9d4e31320f5aadc7e986d5b4ec9ae8dcfd9ac4cf537b", - "review_fingerprint": "0e777addc8ac6ac3994e9d4e31320f5aadc7e986d5b4ec9ae8dcfd9ac4cf537b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 账号调度器(粘性会话/previous_response/TopK 负载均衡/配额自动暂停/传输与能力过滤)的单测,3833 行全文件通读。下游相对上游 aea725f 的 339 行 diff:给测试网关缓存桩补上 DeleteSessionAccountIDIfMatches(L185-L191,对应 gateway_service.go:479 新增的按期望账号条件删除接口);新增 CyberFailoverMatrix(L699-L808)验证下游 SelectAccountWithSchedulerForCapabilityAndPreference(openai_account_scheduler.go:2231)的同类型优先/跨类型兜底/粘性排除/跨组跨平台禁止矩阵;把 TestReportOpenAIAccountScheduleResult 改为两个用例(L2797-L2835),证明迟到的成功上报不再清除仍在生效的模型级冷却、只清已过期条目,以及持久化 model_rate_limits 报 model_rate_limited 原因;ReportOpenAIAccountScheduleResult 三处调用随源码签名从 *Account 改为 int64(openai_account_scheduler.go:2728)。删除的两个上游用例均有归宿:load-batch 过滤原因改由 agent_selection_diagnostics_test.go 以 GetOpenAISelectionDiagnostics 结构化断言覆盖(源码 openai_gateway_scheduling.go:1292 仍在统计),SelectAccountForTokenCount 函数已从代码树整体移除(rg 全库无命中,无死引用)。测试主体是核心调度机制的正确性回归,不属于任何插件域。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S16-svc-account-scheduler-2-review.json", - "Diff vs aea725f: +DeleteSessionAccountIDIfMatches stub L185-L191 mirroring GatewayCache interface (gateway_service.go:479, consumed by openai_sticky_compat.go:219); +TestOpenAIGatewayService_SelectAccountWithSchedulerForCapabilityAndPreference_CyberFailoverMatrix L699-L808; ReportOpenAIAccountScheduleResult call sites switched to int64 at L1572/L3290/L3627 matching openai_account_scheduler.go:2728.", - "Replaced cooldown test: TestOpenAIAccountScheduler_ReportsPersistentModelCooldown L2797-L2812 (model_rate_limited reason via isAccountRequestCompatibleReason, openai_account_scheduler.go:1841) and TestReportOpenAIAccountScheduleResult_SuccessClearsOnlyExpiredModelTransientState L2813-L2835 (late success must not clear an active cooldown).", - "Removed upstream tests traced: legacy load-batch filter-reason coverage moved to agent_selection_diagnostics_test.go (LoadBatchEnabled=true + GetOpenAISelectionDiagnostics; filter stats still built at openai_gateway_scheduling.go:1292 and rendered by openAISelectionFilterStats.summary at openai_account_scheduler.go:1437); SelectAccountForTokenCount has zero occurrences left in backend/ so its regression test had no subject.", - "No production behavior edit and no test execution; assertions were read statically only." - ] - }, - { - "path": "backend/internal/service/openai_agent_identity_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "68bf228a3be4450a5e03084bc850ab4ed9f87ea941a2af9ba7bd100bbab64d7a", - "review_fingerprint": "68bf228a3be4450a5e03084bc850ab4ed9f87ea941a2af9ba7bd100bbab64d7a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI Agent Identity(AgentAssertion)鉴权模式的兼容测试:断言透传构造器输出 AgentAssertion 头且不泄漏私钥、redactAgentIdentitySensitiveBody 抹除 runtime/task/oauth 凭据值、invalid_task_id 在 Forward/ChatCompletions/Anthropic 兼容路由与 AccountTest 上都只恢复一次且不无限循环、WS 连接池 HeadersFactory 在真实拨号时生成鉴权且 ClearAccount 后过期 prewarm 不入池。下游相对上游 aea725f 仅改 13 行断言:不再期望下划线 session_id/conversation_id 头,改为断言两头为空、连字符 session-id 由最终 prompt_cache_key 补齐,证明 Codex 线协议头治理这一核心网关修正。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f 两处:L133-L137(require.Empty session_id/conversation_id,session-id=cache-agent)与 L485-L488(session-id=prompt_cache_key、session_id 为空、两次重试同值);其余 547 行与上游一致", - "被测函数:buildUpstreamRequestOpenAIPassthrough、redactAgentIdentitySensitiveBody、isAgentIdentityTaskInvalidHTTPResponse/WSDialError、validateOpenAIWSBearerToken、newOpenAIWSConnPool.prewarmConns/ClearAccount;本地 stub agentIdentityForwardRepo/accountTestAgentIdentityRepo L503-L547", - "未执行测试,不主张 WS 生产行为。" - ] - }, - { - "path": "backend/internal/service/openai_alpha_search.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "be95c564eea62d4fa03ac8975b770328f2e98b0d010afa7e6be0f522df7979e7", - "review_fingerprint": "be95c564eea62d4fa03ac8975b770328f2e98b0d010afa7e6be0f522df7979e7", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_alpha_search_billing_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "092ff0f57cf23ae8f579f31d2338246e5ddd2ebe5b68d9cf4cfbfd3635286a95", - "review_fingerprint": "092ff0f57cf23ae8f579f31d2338246e5ddd2ebe5b68d9cf4cfbfd3635286a95", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "web 搜索按次计费测试。上游已有:默认价 0.01/次、分组覆盖价、0=免费、负倍率按 0、WebSearchCalls=0 回落 token 路径、APIKey 快照往返保留分组单价。下游相对上游改动:calculateOpenAIRecordUsageCost 增加 account 参数(既有调用补 nil),并新增 TestCalculateOpenAIRecordUsageCost_CindyWebSearchExplicitZeroUnlessGroupOverride,证明第一类 Cindy 账号的 CindyWebSearchModel 按次搜索默认显式 0 费、仅分组覆盖价生效(0.004 x 2 次 x 1.5 倍率=0.012 实际费)——被测为宿主计费对 cindy 目录状态的桥接分支。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:3 处调用签名补 account=nil(L54/L62/L70),+39 行新增 Cindy 零价测试 L74-L111", - "被测分支:openai_gateway_usage.go calculateOpenAIRecordUsageCost L600-L612(cindyCatalogEnabledForBilling+IsCindyAPIKeyAccount+CindyWebSearchModel 时 pricePerCall=0)与 billing_service.go CalculateWebSearchCost L1811", - "未执行测试,不主张实际费率配置。" - ] - }, - { - "path": "backend/internal/service/openai_alpha_search_cindy_native_first_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b5b1657a2de8448e31091b1db88d602e9f0bf7a65041671e9d9669286bf97329", - "review_fingerprint": "b5b1657a2de8448e31091b1db88d602e9f0bf7a65041671e9d9669286bf97329", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_alpha_search_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1c0dcde5534c62bf82ed78dbf3c5276948fd15f2d378874e05833faebaadfc66", - "review_fingerprint": "1c0dcde5534c62bf82ed78dbf3c5276948fd15f2d378874e05833faebaadfc66", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "ForwardAlphaSearch 的行为测试(1029 行,下游 +393)。上游已有 OAuth 线协议保真与 PAT Responses 兜底基础用例;下游新增并证明:PAT 兜底剥离 Responses 专用头且 zstd 出站、体内去除 prompt_cache_key/store(sanitizeOpenAIAlphaSearchBody)、X-Codex-Turn-Metadata 的 session/turn id 按账号作用域改写(scopeCodexAccountIdentityValue)、普通 APIKey 忽略旧桥开关且 404/405 端点缺失换号不写账号错误、401 不标账号错误(含无 auth_mode 的历史 at- token)、SetupToken 429 携带同账号重试窗口、access-state 403 走类型化 failover、上游错误透传不计费(result=nil);另含 Cindy 原生桥用例:绕过旧桥先 /v1/responses 再回退 /v1/messages、无搜索证据或空/错误 tool_result 拒绝成功且不写账号错误、引用即证据。主体证明下游核心转发与计费门修正,Cindy 部分证明宿主桥接。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:主 hunk +179-553(普通 APIKey 桥、Cindy native、PAT backfill 等约 375 行新增),零散:zstd 导入与断言(L140/L179-L193)、身份作用域断言(L97-L104)、模型映射断言(L636)", - "fixture 依赖:firstClassCindyAlphaSearchAccount 定义于 openai_alpha_search_cindy_native_first_test.go L19;被测 openai_alpha_search.go 同切片;whoami 经 httptest 本地伪造(L565-L581)", - "未执行测试,不主张真实上游行为。" - ] - }, - { - "path": "backend/internal/service/openai_apikey_compat.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "6318fdadfd4db9c4703cc8c1b46a2da9cd4322992941b287f5856b04330861f3", - "review_fingerprint": "6318fdadfd4db9c4703cc8c1b46a2da9cd4322992941b287f5856b04330861f3", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "下游新增文件(72 行)。Cindy 受管兼容模式的宿主胶水:SetCindyManagedCompatibility 由 handler 依鉴权分组身份在请求上下文冻结开关(openai_gateway_handler.go L407/L604/L1493/L2903 与 handler/openai_alpha_search.go L47);normalizeCindyManagedPromptCacheKey 是唯一最终线归一器——仅当分组受管且账号是第一类 Cindy APIKey 时,把超过 64 个 Unicode 字符的 prompt_cache_key SHA-256 为 64 位十六进制;旧的账号级 extras 与全局设置仅保留一个回滚窗口、运行时忽略;观测日志只记 normalized 布尔不记键值。分组决定与最终账号身份双重校验,属宿主到 cindy 域的线边界适配而非目录/计价规则。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta(git ls-tree aea725f 无此路径);关键锚点:旧模式常量 L15-L22、身份门 L57-L61、utf8.RuneCountInString>64 才 sha256 L62-L67、脱敏日志 L44-L52", - "调用链:handler 层 SetCindyManagedCompatibility(分组身份) -> service 层 normalizeCindyManagedPromptCacheKey(最终 body,IsCindyAPIKeyAccount 复核账号身份)", - "未执行测试,不主张 64 字符上限的上游出处。" - ] - }, - { - "path": "backend/internal/service/openai_apikey_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "13ac974782065e9a4057d6ee1f3e89b76fc7b479ff029f0abac1569d2ec0a711", - "review_fingerprint": "13ac974782065e9a4057d6ee1f3e89b76fc7b479ff029f0abac1569d2ec0a711", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "下游新增测试(137 行),证明 openai_apikey_compat.go 的门与归一语义:无上下文开关不改写;开关开启但账号非第一类 Cindy(普通 OpenAI APIKey 带旧 extras、或仅凭据像 Cindy 的 legacy 账号)不改写;64/65 边界按 Unicode 字符数(65 个汉字触发、64 个不触发、363 ASCII 触发)、非字符串值跳过;旧 extras(openai_alpha_search_mode=disabled、prompt_cache_key passthrough)被受管运行时忽略且不影响 alpha-search 端点能力;观测日志仅含 normalized 布尔、无 prompt_cache_key 与原值字段。桥接测试,归 cindy-provider。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta;用例锚点:身份门 L32-L59、Unicode 边界表 L61-L99、legacy extras 忽略 L101-L123、日志脱敏 L125-L137(captureStructuredLog 断言无 original_value 字段)", - "被测:normalizeCindyManagedPromptCacheKey/SetCindyManagedCompatibility/observeCindyManagedPromptCacheNormalization(openai_apikey_compat.go L29-L72)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_apikey_responses_probe.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "8cece1f9cf2ac028c48e815d2a8926687f1cef973413d4c915c953b5dea4f4f0", - "review_fingerprint": "8cece1f9cf2ac028c48e815d2a8926687f1cef973413d4c915c953b5dea4f4f0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI APIKey 账号 /v1/responses 端点与工具能力探测(tool_choice=required 强制 function_call;404/405 落 false、其他非 2xx 保守 true、2xx 看 output 是否含 function_call;status=failed 或 max_output_tokens 截断的 2xx 视为结论不充分保持 unknown;网络失败不写标记;国产上游按协议直接落标)。下游相对上游 aea725f 仅 +24/-4:新增 selectResponsesProbeModelContext——第一类 Cindy 账号从 cindy-provider 目录快照取 DefaultTestModel.LiveUpstreamID 作探测模型,快照不可用记 probe_policy_unavailable 并放弃(不误用 OpenAI 默认模型);无 ctx 包装器保留。探测机制留在宿主、探测模型选择委托插件快照,无第二执行体。按 Codex 冻结说明,审查绑定 63a98c8cc 之后的当前磁盘字节(切片旧 sha c8fa5bec 已过期)。静态阅读,未执行探测。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:L82-L111 新增 Context 变体与 LoadCindyCatalogSnapshot 分支、L179-L183 探测入口改用该变体并在 err 时提前返回;其余(responsesProbeVerdictIsConclusive/decideResponsesProbeSupport/isResponsesEndpointSupportedByStatus L282-L346)与上游一致", - "调用链:AccountTestService.ProbeOpenAIAPIKeyResponsesSupport(账号创建/更新后异步)-> accountRepo.UpdateExtra(openai_compat.ExtraKeyResponsesSupported);Cindy 分支 -> LoadCindyCatalogSnapshot(插件目录快照)", - "sha256 由本次审查自算并绑定 post-63a98c8cc 版本;未执行测试或网络探测。" - ] - }, - { - "path": "backend/internal/service/openai_apikey_responses_probe_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5f7dd9a53dd2bf8c6b106b8a47ad6c42378ab0fae5fa49d8c2f32cc503eee4f4", - "review_fingerprint": "5f7dd9a53dd2bf8c6b106b8a47ad6c42378ab0fae5fa49d8c2f32cc503eee4f4", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_astra_pro_mode_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a85a223e038187a721d5054edf58982a29e481005f9de9ecbc8670b4db029179", - "review_fingerprint": "a85a223e038187a721d5054edf58982a29e481005f9de9ecbc8670b4db029179", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "GPT-6 Astra reasoning.mode 经 Forward 全链路保真的集成级测试(native-codex 与 passthrough 两分支 x stream true/false 矩阵、聚合 JSON 与流式 completed 事件都保留 mode/effort、非 Astra 模型仍剥离 mode 并按官方规则 pro 转 max 注入 effort)。下游相对上游 +47 行新增 TestForward_OAuthReasoningModeUsesMappedUpstreamModel:证明 mode 策略按 model_mapping 映射后的上游模型判定——公开别名映射到 Astra 保留 pro 不注入 effort、映射到非 Astra 走 pro 转 max、显式 effort 保留,且策略查询不改写调用方 body 的 model。属下游对核心转发模型策略判定点的修正证明。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:L94-L139 新增映射用例(assistant 到 gpt-6-astra 保 pro;assistant 到 gpt-5.6-sol effort=max;gpt-6-astra 到 gpt-5.6-sol 保显式 medium);其余矩阵用例与上游一致", - "被测:OpenAIGatewayService.Forward 的 reasoning.mode 保留/剥离逻辑(依映射后的上游模型判定),上游 fixture 经 httpUpstreamRecorder 提供 SSE;断言最终 upstream.lastBody", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_astra_pro_retry_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "dabbc0498650b73a3f1560ba0fcb0f1fdc6f5c55cfe7c6ed9654580ef189c9ff", - "review_fingerprint": "dabbc0498650b73a3f1560ba0fcb0f1fdc6f5c55cfe7c6ed9654580ef189c9ff", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Astra pro+max 请求被上游确定性 400(error.param=reasoning.mode)拒绝时的网关行为测试。下游相对上游改写第一个用例:不再断言把上游 error 原样写回客户端,改为断言 Forward 返回 request-scoped 拒绝错误(IsOpenAIRequestRejected、不换号、c.Writer 未提交、客户端得到脱敏的 OpenAIRequestRejected 通用 code/message 而非上游原文),且 Ops 记录 ContinuationDiagnostic(classification=request_validation、param=reasoning.mode);仍只打一次上游、不降级重放。第二个用例不变:rejected-field 重试期间每次重放都保留 mode=pro/effort=max 且仅第二次去掉被拒的 input[0].status。证明下游把确定性 400 从提前提交透传改为延迟渲染+脱敏+诊断的核心修正。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:用例改名 PassesThrough 为 StopsWithoutDowngrade,断言从 recorder.Body 的上游 error 四元组改为 rejected.ClientErrorType/Code/Message + OpsUpstreamErrorsKey 事件(L44-L68);重试保真用例 L77-L101 未变", - "被测:Forward 的确定性 400 处理与 OpsUpstreamErrorEvent.ContinuationDiagnostic(openai_continuation_diagnostic.go 同切片);fixture newOpenAIRejectedFieldTestService/Response 共享", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_bulk_account_settings.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f880bb9d77506e1a5d05f04936660f1b3718678d401eb5e61c3c7af23b5e2e92", - "review_fingerprint": "f880bb9d77506e1a5d05f04936660f1b3718678d401eb5e61c3c7af23b5e2e92", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_business_system_prompt.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "a12981f4d2e105318c8b8693c5f1ea9e750c2e511da917e5e0bbbbcfa0678231", - "review_fingerprint": "a12981f4d2e105318c8b8693c5f1ea9e750c2e511da917e5e0bbbbcfa0678231", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Earlier full prompt-source review matches HEAD byte-for-byte before this delta. All application/snapshot/compiled/target reads and writes now select the current-turn store; carrier undo, frozen per-turn content, account re-admission and response rewriting are unchanged. begin installs a new store at the existing WS turn boundary.", - "evidence": [ - "artifacts/evidence/v027-prompt-turn-cache-review.json: E-WS-SOURCE, E-WS-RED, E-WS-GREEN and E-WS-DIRECT-CONTROLS", - "Targeted passing selectors are bound to the unchanged production delta." - ] - }, - { - "path": "backend/internal/service/openai_business_system_prompt_observability.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "f7004837a896b2e0a79b4256bfc1245969c70c5b0e30e48f7e98432c90d99828", - "review_fingerprint": "f7004837a896b2e0a79b4256bfc1245969c70c5b0e30e48f7e98432c90d99828", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Fully read metadata-only observation builder/logger. It emits byte counts, digests, revision/carrier/transports rather than prompt contents. Deduplication uses the turn store so old observation markers cannot accumulate or suppress a later turn. Logger payload construction is unchanged.", - "evidence": [ - "artifacts/evidence/v027-prompt-turn-cache-review.json: E-WS-SOURCE, E-WS-RED, E-WS-GREEN and E-WS-DIRECT-CONTROLS", - "Targeted passing selectors are bound to the unchanged production delta." - ] - }, - { - "path": "backend/internal/service/openai_business_system_prompt_observability_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8341d81f771047adb551692bcdda23c6a4260d69794bea0c015b28b98afc4947", - "review_fingerprint": "8341d81f771047adb551692bcdda23c6a4260d69794bea0c015b28b98afc4947", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Fully read both unchanged fixtures: derived prompt fields/counts/hash are checked against explicit inputs and independently recomputed SHA256, and absent prompt produces no hash or merged length. These fixtures do not prove actual log transport/redaction and were not rerun because their pure builder is unchanged.", - "evidence": [ - "artifacts/evidence/v027-prompt-turn-cache-review.json: E-WS-SOURCE, E-WS-RED, E-WS-GREEN and E-WS-DIRECT-CONTROLS", - "Static review only; unchanged pure metadata builder was not rerun." - ] - }, - { - "path": "backend/internal/service/openai_chat_reasoning_replay.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "bf2693d86e4ee91d026b376e16bc26eb285722730e24085bde4289891e169898", - "review_fingerprint": "bf2693d86e4ee91d026b376e16bc26eb285722730e24085bde4289891e169898", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增文件(729 行)。Chat Completions 转 Responses 桥的 reasoning 批次重放缓存:把客户端 Chat 历史中已完成且可逆的 assistant 工具批次投影为哈希键(策略哈希+前缀哈希+可见投影),命中后把缓存的原始 Responses output(含 encrypted_content)拼回 wire input;记录器只在收到权威 response.completed 且下游投影逐字节一致时才入库;invalid_encrypted_content 拒绝时按 payloadHash CAS 删除对应批次。重放规则(enabled/MaxToolCalls/ChatFields/OutputKinds/AllowOmittedReasoning)经 readOpenAIReplayRules 从 codex-runtime 插件获取(plugins/codex-runtime/recovery/policy.go ReplayPolicy),宿主只执行不定策——无第二执行体。缓存作用域绑定 UserID/APIKeyID/GroupID/AccountID+来源身份哈希(openai_reasoning_recovery.go L172-L195),未见跨租户泄漏;I/O 全部经 budget 限额、批量查询上限 OpenAIReasoningStateMaxLookupEntries、批次字节上限 256KB。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta;关键锚点:投影归一 L60-L99、原始字段白名单 L101-L130、前缀哈希(instructions/tools/parallel_tool_calls/text/previous_response_id/conversation+input)L147-L172、prepare 主流程 L270-L399、CAS 失效 L416-L435、Commit 复核规则仍启用 L437-L459、录制器状态机 L571-L702", - "调用链:ForwardAsChatCompletions -> prepareOpenAIChatReasoningReplay(规则 plugin_codex_recovery.go L59 readOpenAIReplayRules -> codex-runtime 插件);scope buildOpenAIReasoningScope 绑定租户与账号", - "未执行测试;不主张缓存后端(GatewayCache)的生产可用性。" - ] - }, - { - "path": "backend/internal/service/openai_chat_reasoning_replay_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1919ab8fc91c6e2560ff0a72fe52432583aff5dbae94bbfc1228eb4fe6a09a68", - "review_fingerprint": "1919ab8fc91c6e2560ff0a72fe52432583aff5dbae94bbfc1228eb4fe6a09a68", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(494 行),证明 reasoning 重放缓存的关键不变量:录制器需权威 completed 输出与下游投影双证据才产出批次(response.failed/incomplete/error 或投影改写即拒绝);流式投影按 delta 聚合且推理 delta 不一致即失效;不可逆批次矩阵(custom/builtin 工具、未知输出类型、refusal、in_progress、空参数、数字 call_id、namespace、缺 summary、重复 call_id)全部拒收;可选 reasoning 匹配与批次键在 omitted/alias 情形一致;命中后 wire input 精确还原原始三项 output(保留未知字段与大整数 9007199254740993);miss 变体(缓存缺失/读错/账号级关闭/未知租户/换账号/改 reasoning/改前缀/actual 前缀不符)一律不改 input;invalid_encrypted_content 一次性恢复并 CAS 删除+负缓存,恢复失败不得进入换号 failover;规则字段或版本变化改变缓存身份。测试直接引用 codex-runtime 插件 ReplayPolicy 作为规则 fixture。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta;锚点:录制器完成性 L55-L81、流式变体 L83-L112、不可逆矩阵 L114-L136、往返 L260-L301、miss 矩阵 L303-L356、一次性恢复+CAS L358-L414、重复 JSON 成员拒绝 L427-L435、规则身份 L475-L494", - "fixture:import codexrecovery(HTExplicit/sub2api-plugins/codexruntime/recovery)L17 与本地 openAIChatReplayTestCache L166-L223;被测 openai_chat_reasoning_replay.go 同切片", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_cindy_continuation.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "351ac761a50bb9728b7389528620939f7c2c7beb15f3449d10fec7d0fe1d2a62", - "review_fingerprint": "351ac761a50bb9728b7389528620939f7c2c7beb15f3449d10fec7d0fe1d2a62", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_cindy_continuation_ingress_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5a66d3f947551a0b00a1dd8f789960fd37f25fd055f72eea50444b71a6e0a5fe", - "review_fingerprint": "5a66d3f947551a0b00a1dd8f789960fd37f25fd055f72eea50444b71a6e0a5fe", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_cindy_continuation_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f2de6a12e859c61a0caae6d2157c34af45162273ab86de59911196b841c72714", - "review_fingerprint": "f2de6a12e859c61a0caae6d2157c34af45162273ab86de59911196b841c72714", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_cindy_http_wsv2.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "f62cc59991582aeef57842461a0c5767129a26267554213b74403cab769e67d4", - "review_fingerprint": "f62cc59991582aeef57842461a0c5767129a26267554213b74403cab769e67d4", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_cindy_http_wsv2_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e50c525d170d61f67a29e8e64338b6531948f5c861413878ed33d7dad581ed4d", - "review_fingerprint": "e50c525d170d61f67a29e8e64338b6531948f5c861413878ed33d7dad581ed4d", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_cindy_opaque_binding.go", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "b70c553e8874fad9ff8323a0832c1ae036f5d2c0b6e0cb201e5d3661f7fa66eb", - "review_fingerprint": "b70c553e8874fad9ff8323a0832c1ae036f5d2c0b6e0cb201e5d3661f7fa66eb", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI Responses 网关的“不透明续接”账号亲和机制:从 reasoning/compaction 项的 encrypted_content / signature 载体做 JSON 规范化后加盐 SHA-256 得到 cindy_opaque_v1_ 绑定 ID,经 OpenAIWSStateStore.BindResponseAccount 绑定到实际 account.ID,并提供四个选择器(Cindy / 旧 Laxa 投影 × opaque / legacy session)在续接时把请求钉回同一账号,逐步校验 excludedIDs、分组匹配、DB 复核、IsCindyAPIKeyAccount 或 IsLegacyCindyAPIKeyAccount 身份、传输兼容与并发槽位。整文件为下游新增,上游无此路径;rg 显示 plugins/cindy-provider 完全没有 opaque/continuation/BindResponseAccount 代码,身份谓词来自宿主 cindy_identity.go,因此这是网关调度层的通用续接机制而非第二执行器,归 core-quota-and-protocol。观察:多个绑定 ID 指向不同账号时返回 errCindyOpaqueBindingConflict 但被上层映射为 StoreUnavailable 而不是 400,属于 fail-closed 语义选择,未列为缺陷;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S55-cindy-rest-T5-review.json", - "L18-L125: cindyOpaqueBindingIDsFromItem/cindyOpaqueBindingID/canonicalCindyOpaqueCarrier/normalizeCindyOpaqueBindingIDs 及 FromResponsePayload(output、response.output、item、根)/FromRawItems;域分隔盐 \"sub2api:cindy:opaque:v1 NUL NUL \",signature 仅对 reasoning/compaction/compaction_summary 计入。", - "L127-L268: LookupCindyOpaqueContinuationBinding 逐 ID 调 LookupOpenAIContinuationBinding(openai_ws_state_store.go:114),账号不一致→StoreError+errCindyOpaqueBindingConflict;selectAccountByOpaqueContinuation 依次检查 excludedIDs、getSchedulableAccount、openAIAccountMatchesSchedulingGroup、recheckSelectedOpenAIAccountFromDB(PlatformCindy 或 PlatformOpenAI)、身份谓词、isOpenAIAccountTransportCompatible、tryAcquireAccountSlot/WaitPlan。", - "L309-L413: selectAccountByLegacySessionContinuation 用 getStickySessionAccountID 复原 pre-v0.1.179 会话并顺带 bindCindyOpaqueContinuationAccount;gin 版 bindCindyOpaqueContinuationAccount 仅对 IsCindyRuntimeCompatibleAPIKeyAccount 账号写入,失败只记录 group_id/account_id 无密钥。调用方:handler/openai_gateway_handler.go:649,695,931-946,2961-2997,3272-3306;openai_gateway_forward.go:1124,1518;openai_gateway_passthrough.go:683,2367,2896,3024;openai_gateway_response_handling.go:642,1901,2203;openai_ws_forwarder_ingress.go:893,2071。", - "边界:rg --no-config -i 'opaque|cindy_opaque_v1|encrypted_content|BindResponseAccount|continuation' plugins/cindy-provider 无命中,插件不持有该规则;不宣称运行时行为或测试通过,文件为下游新增(git ls-tree aea725f 无此路径)。" - ] - }, - { - "path": "backend/internal/service/openai_cindy_opaque_binding_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "58e220b945e3e847685ffdb8a3634225a02fb251d13238e06e000ba5b620556e", - "review_fingerprint": "58e220b945e3e847685ffdb8a3634225a02fb251d13238e06e000ba5b620556e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "针对 openai_cindy_opaque_binding.go 中 LookupCindyOpaqueContinuationBinding 的单元测试:用嵌入 OpenAIWSStateStore 接口、只覆盖 GetResponseAccount 的假 store,断言多个绑定 ID 里命中/未命中的先后顺序不影响结果(均为 Hit 且 AccountID=731)、全部未命中返回 Miss、两个 ID 分别指向 731/732 时返回 StoreError 且 ErrorIs errCindyOpaqueBindingConflict、任一 ID 的 store 错误无论出现在命中前后都以 StoreError 原样透传。被测对象是宿主网关的续接亲和机制而非插件代码,与源文件同属 core-quota-and-protocol;下游新增测试文件,只做静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S55-cindy-rest-T5-review.json", - "L11-L22: cindyOpaqueBindingLookupStore 嵌入 OpenAIWSStateStore 并按 responseID 查 accountIDs/errors 两张 map 实现 GetResponseAccount,其他接口方法留空指针(未被调用路径触及)。", - "L24-L56: TestLookupCindyOpaqueContinuationBindingUsesAnyUnanimousSurvivingBinding 两个子用例 miss-before-hit / hit-before-miss,均 require Hit、731、NoError,证明 normalize 排序后聚合与输入顺序无关。", - "L58-L118: TestLookupCindyOpaqueContinuationBindingPreservesMissConflictAndStoreError 覆盖 all miss→Miss/AccountID 0;conflicting hits(731 vs 732)→StoreError+errCindyOpaqueBindingConflict;store error before/after hit→StoreError 且 ErrorIs 注入的 redis unavailable 错误。", - "边界:被测函数在 openai_cindy_opaque_binding.go L127-L153,plugins/cindy-provider 无对应实现;本文件无 //go:build 标签(对比 plugin_cindy_codex_test.go 的 unit 标签),仅陈述断言内容,不宣称测试已运行或通过。" - ] - }, - { - "path": "backend/internal/service/openai_codex_account_identity.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "17a7871572c5d5701731e1f2419628e4e0870c19b0e9149a8b5cc7e40318a01c", - "review_fingerprint": "17a7871572c5d5701731e1f2419628e4e0870c19b0e9149a8b5cc7e40318a01c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 网关按 (API Key, OAuth 凭据) 作用域改写客户端标识(session/thread/window/request-id/prompt_cache_key/installation)的宿主收口。下游相对上游把 v1 按 kind 分种子的改写改成 v2 同值同映射:UUIDv7 保留 48 位时间戳与版本位、\":\" 与 \":\" 只改写 uuid 段,保住真实 Codex 的 root 线程 session==thread==request-id==prompt_cache_key 形态不变式;并修正头形态(永不发 x-codex-installation-id 头,新增 fill/ensureCodexSessionIdentityHeaders 删除下划线 session_id/conversation_id、按最终会话值补齐连字符头)。这是核心网关协议仿真的正确性修复,不是插件业务规则;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: codexAccountIdentityNamespaceVersion v1->v2 (L20), kind parameter removed from scopeCodexAccountIdentityValue (L108-127), new scopeCodexIdentityUUID keeps UUIDv7 time bits (L141-155), header switch drops x-codex-installation-id and skips session_id (L286-306), new fillCodexSessionIdentityHeaders/ensureCodexSessionIdentityHeaders (L325-353).", - "Call chain: prepareCodexAccountIdentitySource/applyCodexAccountIdentity* consumed by openai_gateway_forward.go, openai_gateway_passthrough.go, openai_gateway_messages.go, openai_gateway_chat_completions.go, openai_alpha_search.go, openai_ws_forwarder_*; namespace falls back to codexFingerprintSeed then setup-token bearer hash, never local row IDs.", - "Edge noted, not filed as finding: for a crafted value 'uuidA:uuidB' only the head UUID is rewritten (first-colon split, L117-125); real Codex forms are '', ':', ':' so the invariant holds for legitimate traffic.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_account_identity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "61bb80d91b2faf5ba8b430649023675ef53f23c15f530053d4e6a6d277491cea", - "review_fingerprint": "61bb80d91b2faf5ba8b430649023675ef53f23c15f530053d4e6a6d277491cea", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "账号作用域改写的单测。断言证明:同一 OAuth 凭据命名空间跨本地行稳定(chatgpt_account_id/user_id、seed、setup-token 哈希且不泄原 token)、影子账号解析到父凭据并在 failover 时覆写 gin context、HTTP 与 WS 出站从同一原始值派生同一身份。下游 delta 把断言改到新头形态:无下划线 session_id、installation id 不作为头、以最终 prompt_cache_key 补齐 session-id、HTTP/WS 同源等价。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f (L114-121, L135-175): asserts req.Header session_id empty + session-id filled from final prompt cache key; header loop switched from session_id/x-codex-installation-id to hyphen-only set; scopedBody uses scopeCodexAccountIdentityValue for HTTP/WS parity via buildUpstreamRequest and buildOpenAIWSHeaders.", - "Subjects are core gateway functions (OpenAIGatewayService.buildUpstreamRequest, buildOpenAIWSHeaders, codexAccountIdentityNamespace); no plugin-owned rule asserted.", - "Statically read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_codex_client_identity.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0d74d4eb32272dd3479fa9ae89ffc6ef8bb1e2eaddc08aa19385159a90cb6495", - "review_fingerprint": "0d74d4eb32272dd3479fa9ae89ffc6ef8bb1e2eaddc08aa19385159a90cb6495", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "保留 generic wrappers,并为已有账号增加显式 context/account 版本;Account.CodexClientIdentity 及 Extra 检查/派生始终保持实际 scope。创建前 helper 使用已知 type 的 ID=0 临时宿主对象。后台回填不再预先获取全局 domain lease,而在每个适用账号下获取现有 typed/ID lease,再以 bound context 和 UpdatedAt CAS 写入,仅后台维护可跳过不适用账号,未触及显式管理员批量目标验证。", - "evidence": [ - "valid/userAgent/derive/fromExtra account-aware variants", - "ensureCodexClientIdentityExtra pre-create wrapper", - "RunOnce scoped available -> bindProcessExtensionContext -> UpdateExtraIfRevision", - "v027-astra-codex-scope-review.json:T-001", - "v027-astra-codex-scope-review.json:T-003", - "v027-astra-codex-scope-review.json:T-004", - "Source review covers the complete named file; synthetic tests are not real token, model or database validation. Unchanged repository CAS code is not retested here." - ] - }, - { - "path": "backend/internal/service/openai_codex_client_identity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9309d13d03da8537624a09fb1f8c426742a786de8cb51cfdcad43d36a14008c8", - "review_fingerprint": "9309d13d03da8537624a09fb1f8c426742a786de8cb51cfdcad43d36a14008c8", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_codex_context_contract.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "69264ef8e0020cf632c8f80b2702fed8230c3c1c24fef9cc7b645d7bca0b1071", - "review_fingerprint": "69264ef8e0020cf632c8f80b2702fed8230c3c1c24fef9cc7b645d7bca0b1071", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增的离线自检:用确定性 fixture 走生产纯函数 ResolveModelContextCapacity + ApplyModelContextCapacityToFields,校验 context 容量优先级 custom>official>upstream>default、默认 200000、protected 清单与哨兵字段不被触碰,输出 CODEX_CONTEXT_CONTRACT 状态行。经 backend/cmd/server/main.go 的 --verify-codex-context-contract 旗标调用,无配置/网络/DB。属于核心容量策略的守护机制,不承载某插件业务规则;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "New downstream file; whole file is the delta.", - "Wiring: backend/cmd/server/main.go L66 flag verify-codex-context-contract -> runCodexContextContractVerificationWith -> service.VerifyOfficialCodexContextContract (main.go L128).", - "Resolver/projection subjects live in model_context_capacity.go and group_model_capacity.go (other slices); fixture checks fail closed on sentinel/count/duplicate/policy mismatch (L81-123).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_context_contract_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "519bd3ed42859499884e146cd02c6a04a2e304ac48f3bea83e11485e48aea83a", - "review_fingerprint": "519bd3ed42859499884e146cd02c6a04a2e304ac48f3bea83e11485e48aea83a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试:证明合同自检成功行等于常量、fixture 确定性可通过,且对 8 类突变(坏 envelope、错 custom 值、优先级来源错位、默认值漂移、不安全 compact 阈值、protected 值变动、哨兵变动、无关能力变动)与缺失/重复 model 一律报错(fail closed)。主体是核心容量策略守护机制;测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "New downstream file; whole file is the delta.", - "Anchors: TestModelContextCapacityContractFailsClosed table (L23-32) mutates buildOfficialCodexContextContractFixture output; missing/duplicate model subtests (L43-58).", - "Statically read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_codex_context_window_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ba9416364881904a13a2cd6d68a8017ded59f0da1de96476c712c94bf3a440dc", - "review_fingerprint": "ba9416364881904a13a2cd6d68a8017ded59f0da1de96476c712c94bf3a440dc", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Codex models manifest 的 context 窗口同步/交集/注册表补全测试。下游 delta 改造 TestCodexContextWindowRegistryEnrichment:区分同步观测值与公开投影值(新增 wantPublicWindow/wantPublicMax/wantSource),断言第三方 relay 主机上游声明优先、上游沉默才回落 official 注册表,并断言 context_capacity_source 标签。证明下游\"上游优先\"容量策略对上游行为的修正;测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f (L107-163): case 'upstream default remains ceiling' became 'upstream default without maximum' (max observed 0, public 272000/272000, source=upstream); registry case asserts source=official; new asserts on catalog.Metadata vs manifest projection.", - "Subjects: AccountTestService.SyncUpstreamModelCatalog and GatewayService.BuildCodexModelsManifestForGroup (openai_codex_models_service.go, this slice).", - "Statically read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_codex_fingerprint.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c7f7516766931d90c7adbfee5d1f3cb5f6862f851383cb30769031873c28e72b", - "review_fingerprint": "c7f7516766931d90c7adbfee5d1f3cb5f6862f851383cb30769031873c28e72b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OAuth 账号设备指纹收敛引擎(off/device/session/full 四档,installation/session/thread/turn/window 派生与头/体改写,map 版与透传 raw 字节版共享同一核心)。下游 delta:默认收敛档由 codex-runtime 插件的 codex.identity.plan 提供(显式配置优先,插件不可用回落上游 off 默认);种子与 CodexClientIdentity 改为系统管理字段(创建时铸造、更新时保留库值、剥离表单值);头形态修正(installation id 永不作为头、下划线 session_id 只同步不新增);turn metadata 增加与最终 UA 配套的 sandbox。宿主保留通用收敛机制,域默认值在插件——无第二执行者;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: codexFingerprintModeFromExtraContext + invokeCodexIdentityPolicyForAccount('codex.identity.plan') (L121-134), codexFingerprintModeExplicit split (L139-150), prepareCodexFingerprintExtraForCreate/Update rework (L170-208), GetCodexFingerprintMode gated by codexIdentityPolicyAvailable (L238-249), applyCodexFingerprintHeaders drops x-codex-installation-id and conditions session_id (L402-436), new alignSandboxWithUserAgent/turnMetadataFields (L440-459).", - "Plugin boundary: plugin_codex_identity.go invokeProcessExtensionCached with 1s timeout, ErrExtensionOperationDisabled -> upstream default; failover safety via stageCodexFingerprintIDs unconditional overwrite + accountID guard (L30-49).", - "Minor non-finding: doc comment of ShouldEnsureCodexFingerprintSeedForExtraUpdates is duplicated verbatim (L220-226).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_fingerprint_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "06a0aa159b5295f6fbab559f6f86f8f881b0a7c7b2c24172d4b433e2c360ee4c", - "review_fingerprint": "06a0aa159b5295f6fbab559f6f86f8f881b0a7c7b2c24172d4b433e2c360ee4c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "指纹收敛引擎的单测(948 行)。断言证明:确定性 UUIDv4 派生、缺省/空/非法模式在插件默认下为 device 而显式 off 生效、启用档必须有合法种子、device/session/full 三档头体改写、头体 turn_id 与 turn_started_at 一致、raw 字节版与 map 版逐点等价、prompt_cache_key 只在可证明为 body session 默认值时改写、failover 时 staged IDs 不跨账号泄漏、透传路径出站头收敛与新头形态(无下划线 session_id、无 installation-id 头、sandbox 跟随账号身份)。下游 delta 即把 #5610 时代的默认 off 断言翻转为插件提供的默认 device 并适配新头形态。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: TestGetCodexFingerprintMode default cases off->device (L69-77), TestResolveCodexFingerprintIDsFromRequest_DefaultIsOff renamed _DefaultIsDevice with NotNil+device asserts (L136-142), header asserts switched to empty x-codex-installation-id/session_id and identity.Sandbox (multiple hunks).", - "Map/raw equivalence harness rawVsMapClientMetadata + cloneCodexFingerprintIDsForTest (L569-611) covers passthrough hot path parity.", - "Finding recorded: stale comment above TestResolveCodexFingerprintIDsFromRequest_DefaultIsDevice still claims default returns nil per #5610 (L134-135), contradicting the assertions below it.", - "Statically read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_codex_identity.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2d07862451527975570c845113676af1b8514b265fbc783d9f0c578eaf61bfd7", - "review_fingerprint": "2d07862451527975570c845113676af1b8514b265fbc783d9f0c578eaf61bfd7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Codex 出站身份三元组(UA/originator/version)的规范化与收口:版本校验拒绝任意字节、版本门槛 0.144.0(低于则上游 404)、强制统一开关与 pair 兜底。下游 delta 新增 ForceCodexCLI 进程级快照(凭据面与推理面共用同一显式 UA 策略,避免同一账号双 UA 出站)与账号级收口 enforceCodexIdentityHeadersForAccount(Context)——强制统一时用账号持久化/种子派生的 TUI 身份而非全局规范身份,解析经 plugin_codex_identity.go 的插件策略。通用宿主身份机制;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: new codexForceCLI atomic + SetCodexForceCLIEnabled + codexAccountIdentityOverrideUA (L63-80), new resolveCodexOutboundIdentityForAccount / enforceCodexIdentityHeadersForAccount(Context) (L272-304); rest unchanged (enforcement default on, pairCodexIdentityHeaders fallback).", - "Call chain: resolveCodexOutboundIdentityForAccountContext (plugin_codex_identity.go) -> codexIdentityPolicyAvailable / codex.identity.plan; consumers include OAuth refresh (see client_identity_test) and gateway builders.", - "Version handling: codexClientVersionFromUA falls back to compile-time codexCLIVersion when below codexUpstreamMinVersion (L186-192); enforcement only for requests already carrying originator (L243, L289).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_identity_snapshot.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0d0fa5e3fb3bdbd9429396cc7931065b4e085f5e7280f3e355a96cfe22502c0b", - "review_fingerprint": "0d0fa5e3fb3bdbd9429396cc7931065b4e085f5e7280f3e355a96cfe22502c0b", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "transport、持久 profile 校验和 UA 解释使用实际 source.ID/type 与当前 ctx;routed 账号的指纹默认策略仍由其自身账号对象决定。诊断没有真实 token 或上游访问,不再借共享 domain 解释类型/灰度不匹配账号的 profile;输出字段形状未扩大。", - "evidence": [ - "codexTransportPlan source.ID", - "codexClientIdentityFromExtraContext", - "source.codexClientIdentityContext/userAgentForAccountContext", - "v027-astra-codex-scope-review.json:T-001 diagnostic-snapshot and type mismatch", - "Source review covers the complete named file; synthetic tests are not real token, model or database validation. Unchanged repository CAS code is not retested here." - ] - }, - { - "path": "backend/internal/service/openai_codex_model_metadata_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0fa55871245fc9d599074e5f218d86c0890ed19e54d5581ed23ed437708ce69a", - "review_fingerprint": "0fa55871245fc9d599074e5f218d86c0890ed19e54d5581ed23ed437708ce69a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Codex 模型清单元数据聚合测试(765 行):Astra Ultra 工作流字段跨同步/别名/组生成存活且不跨账号外泄、工具能力按账号作用域与共享声明交集、null/false 的活值保留、瞬时不可调度账号仍参与交集而持久禁用账号不参与、跨平台别名歧义 fail closed、路由规则决定别名归属。下游 delta 是容量来源纪律:旧注册表容量不再当作上游观测(默认 200000 + context_capacity_reason=no_verified_capacity / account_query_failed),上游观测需要容量快照且投影带 context_capacity_source 标签。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: TestBuildCodexModelsManifestForGroupUsesSyncedAccountMetadata renamed ...UsesSyncedNonCapacityMetadataWithoutTrustingLegacyCapacity, expects 200000/default/no_verified_capacity instead of 1000000 (L144-195); intersect tests add SetUpstreamModelContextCapacitySnapshot and assert context_capacity_source (L308-355, L358-424); availability-failure test renamed KeepsNonCapacityFallback... expecting default+account_query_failed (L513-544).", - "Subjects: buildCodexModelsManifestForAccounts / BuildCodexModelsManifestForGroup / completeAPIKeyCodexModelsManifestMetadata / adjustAPIKeyCodexModelsManifest (openai_codex_models_service.go, this slice).", - "Trailing orphan comment at EOF (L765, '// Scenario: mixed groups prefer capability metadata synced for the routed account.') already exists verbatim in upstream aea725f (upstream line 744) - inherited, not downstream debris.", - "Statically read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_codex_models_pinned.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c2037d7a9256eaf9970a2476a21f6c6dca21f3b778c4d835f0cf80582e929fdd", - "review_fingerprint": "c2037d7a9256eaf9970a2476a21f6c6dca21f3b778c4d835f0cf80582e929fdd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "钉选清单模式:按组配置的账号(忽略调度器优先级/限流窗口)并发拉取 Codex 清单,按 slug 以配置顺序去重合并;部分失败记警告、全失败回抛最后错误、无可用账号返回 ErrNoPinnedCodexModelsAccounts。下游 delta 新增 mergePinnedModelsCapacityProvenance:合并时保留每个成功源的原始 body 供容量聚合,只有赢得公开行的 model 继承 protected 来源,且经 cloneOpenAIModelsResponse 深拷贝后按值改写 visibleModels,不污染共享缓存对象。通用宿主清单机制;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: FetchPinnedCodexModelsManifest now attaches capacitySources/capacityProtectedModels (L142-147); new mergePinnedModelsCapacityProvenance (L153-198) with first-seen visibility scoping.", - "Concurrency check: fetchPinnedOpenAIModels goroutines write disjoint slice slots, WaitGroup joins before reads, ctx.Err checked post-join (L241-256); codexModelCapacitySource entries are value-copied before visibleModels reassignment so the cloned response is not mutated.", - "Callers: handler /backend-api/codex/models pinned path and group manifest config; helper types OpenAIModelsResponse/cloneOpenAIModelsResponse defined in openai_codex_models_service.go (this slice).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_models_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a95e49670a9cd584a509a2accd7f6be84a8e0c4a2c4b61d5193bac5737240d6b", - "review_fingerprint": "a95e49670a9cd584a509a2accd7f6be84a8e0c4a2c4b61d5193bac5737240d6b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Codex 模型清单服务(3005 行):组配置清单构建、组可见性/能力交集(图像输入、search 工具、工具能力、推理档)、OAuth/API Key 上游拉取(15s 超时、1MB 缓存预算、512 条 LRU、fresh/stale/miss 三段 TTL + singleflight 后台刷新、ETag 304 续期)、可重试错误分类与 failover 适配、API Key 清单补全/纠正、Cindy 目录投影与合并。下游 delta:容量来源溯源(codexModelCapacitySource + capacitySources/capacityProtectedModels 贯穿拉取/合并/缓存预算/克隆)、容量目录 loadGroupModelCapacityCatalog 取代旧 loadCodexGroupCatalogAccounts(职责迁移非复制)、NormalizeCodexModelsManifestFailoverError 接入网关重试契约、清单 401 喂给账号健康状态机(#4544)且防二次惩罚、出站身份走账号级解析、Cindy 清单构建/投影改为消费插件提供的 CindyCatalogSnapshot(cindy-provider 业务数据在插件侧,宿主只做合并投影,无第二执行者)。注意:本文件按 63a98c8cc 之后的冻结版审阅(切片清单 sha 已过期,此处记录新 sha)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Reviewed at the FROZEN post-63a98c8cc on-disk bytes; sha256 recomputed read-only: a95e4967... (slice manifest had 8197d2ef...). 63a98c8cc ('fix(cindy): bind model mapping and pricing to request snapshots') threads a request-scoped CindyCatalogSnapshot through openAIModelsRequest/fetch/projection instead of process-global feature flags (L1609, L1799-1823, L2060-2073, L2136-2166).", - "Delta vs aea725f anchors: codexModelCapacitySource + newCodexModelCapacitySource (L124-141); capacity-aware BuildGroupConfiguredCodexModelsManifest/BuildCodexModelsManifestForGroup with fail-closed capacity + legacy metadata fallback (L164-206, L843-876); removed loadCodexGroupCatalogAccounts (moved to group_model_capacity.go loadGroupModelCapacityCatalog); NormalizeCodexModelsManifestFailoverError + accountHealthHandled marker (L1460-1517, L1877-1894); cache set enforces body budget across capacitySources (L1655-1699); manifest fetch identity via resolveCodexOutboundIdentityForAccountContext + version header floor (L1773-1792); conversion projects observed capacities without persisting (L2514-2539); CompleteAPIKeyCodexModelsManifestForClient defers capacity to final group merge (L2576-2578); cloneOpenAIModelsResponse deep-copies capacity fields (L2904-2935).", - "Call chain: consumed by handler openai_codex_models_handler.go and group manifest paths; helpers groupCodexModelMetadata/applyCodexToolCapabilities live in openai_codex_model_metadata.go, capacity resolve/projection in group_model_capacity.go + model_context_capacity.go (other slices); Cindy snapshot loading via LoadCindyCatalogSnapshot (cindy_catalog_snapshot.go, other slice).", - "No defect found at this read: cache is bounded (512 entries, per-entry byte budgets), singleflight refresh uses detached 15s context by design, pinned/manifest 401 handling suppresses double health penalties, error bodies capped at 2048 bytes and agent-identity-redacted.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_models_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6bfe610c8a1fee39c9ac1f96d1e99e83130e61f2797c6cb89c62b5eda509a830", - "review_fingerprint": "6bfe610c8a1fee39c9ac1f96d1e99e83130e61f2797c6cb89c62b5eda509a830", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "模型清单服务的单测(4520 行)。断言证明:配置目录 descriptor 的完整 ModelInfo 契约与各家族(DeepSeek/Grok/Claude/GPT/自定义)默认档位、service tier 声明、专用图片模型剔除、组能力交集与 fail closed、缓存三段时效(新鲜零上游/乐观旧值后台单飞/超期同步等待且失败不回旧值)、缓存键隔离(账号/凭据/上游/版本/头覆盖/代理/Cindy 投影/标准列表格式)且容量覆写不进缓存键、512 条与字节预算上限、客户端过滤不污染共享缓存、singleflight 刷新在调用方取消后存活(15s 独立 deadline)、清单 401 喂账号健康状态机而 API Key 401 不 failover 不禁号(#4544)、agent identity 恢复一次且错误脱敏、无效 envelope 可重试且不入缓存、Cindy 目录投影/合并/rollout 子进程隔离(env 开关)、容量投影保护行字节不变。下游 delta 即这些容量溯源/缓存/Cindy 快照行为的新增与改名。测试静态阅读,未执行;文件内的 httptest 服务与 exec 子进程仅为测试自身设计,本审阅未运行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f is +1731/-x lines: new capacity provenance & cache-bound tests (TestFetchCodexModelsManifestAPIKeyCacheBoundsEntriesAndBodySize L3141-3191, TestBuildOpenAIModelsCacheKeyKeepsCapacityOverridesLocal L2687-2693), 401 health tests (L3507-3618), shared-refresh/cancellation tests (L2924-3057), Cindy rollout subprocess helpers (L2486-2568), rust-v0.147.0 ModelInfo contract test (L2235-2413).", - "Subjects are openai_codex_models_service.go functions of this slice; Cindy snapshot subjects live in cindy_catalog_snapshot.go (other slice).", - "Note: this test file still matched the slice sha (6bfe610c...) even though its subject file moved to the frozen 63a98c8cc version; the tests exercised here (runCindyCodexCatalogEnabledTest env-gated) already target the snapshot API.", - "Statically read only; the tests were not executed." - ] - }, - { - "path": "backend/internal/service/openai_codex_request_compression.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3d7c9620c5e57c00d46e027ac018070f3d99f69b58ac900f9119d433fdfe0d88", - "review_fingerprint": "3d7c9620c5e57c00d46e027ac018070f3d99f69b58ac900f9119d433fdfe0d88", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增文件:OAuth-like 账号发往 Codex /responses 的 POST 在最终发送副本上做 zstd level3 压缩(与 codex-rs 客户端一致:无校验和、2MB 窗口;帧差异如实注释),调用方持有的请求保持明文供恢复/诊断/重试。是否压缩由 codex-runtime 插件的 codex.transport.plan 决定(prepareCodexTransport 经 plugin_codex_transport.go),宿主只保留 body 所有权/完整读取/可重放性等 IO 执行(ungated 执行器);编码失败退回明文,不可重放请求读取失败显式报错、绝不发送截断前缀。doOpenAICodexUpstream 为全部 Responses POST 的统一发送入口。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "New downstream file; whole file is the delta.", - "Plugin boundary: prepareOpenAICodexWireRequest -> prepareCodexTransport (plugin_codex_transport.go L36) -> codex.transport.plan with 1s timeout; ErrExtensionOperationDisabled -> plain passthrough; plan.Compress gates prepareOpenAICodexWireRequestUngated (L72-124).", - "Callers: openai_alpha_search.go, openai_gateway_forward.go L1223, openai_gateway_chat_completions.go L514, openai_gateway_messages.go L453, openai_gateway_cc_pipeline.go L265.", - "Resource safety: sync.Pool encoder reuse with WithEncoderConcurrency(1) (L28-39); GetBody snapshot path leaves original request untouched (L83-94).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_request_compression_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3999cd49347f29a7fe08da261d883e48b4372036ebe55cc965ada30c27b0fb8f", - "review_fingerprint": "3999cd49347f29a7fe08da261d883e48b4372036ebe55cc965ada30c27b0fb8f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试:证明仅 OAuth-like + /backend-api/codex/responses POST 压缩(compact、API Key、插件计划关闭时不压缩)、zstd 魔数与无校验和帧形态、解压等于原文、wire 克隆可重放而原请求保持明文可重读、读取失败时不可重放请求显式报错/可重放请求退回明文(绝不发截断前缀)、WS 直连 HTTP 客户端禁用自动 gzip。经 withCodexTransportFixture 桩住插件计划以覆盖 quota 与网关两条路径同策略。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "New downstream file; whole file is the delta.", - "Anchors: TestPrepareOpenAICodexWireRequestCompressesOnlyCodexStreamingTurns (L19-88) incl. zstd magic 0x28b52ffd and checksum-bit-zero asserts; TestPrepareOpenAICodexWireRequestNeverSendsTruncatedBody (L116-146); TestOpenAIWSDirectHTTPClientDisablesCompression (L149-153).", - "Statically read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_codex_ticket.go", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "97204550e1f3ce6763846af89c9fadf76ffb87cd1bb16eac5ec1530692f63d65", - "review_fingerprint": "97204550e1f3ce6763846af89c9fadf76ffb87cd1bb16eac5ec1530692f63d65", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_codex_ticket_scheduler_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fad097613d6552a00abd81b72a45c2ada0ea323193ed20dd77fab1d6fbfbaa3f", - "review_fingerprint": "fad097613d6552a00abd81b72a45c2ada0ea323193ed20dd77fab1d6fbfbaa3f", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_codex_ticket_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e4d0d48eb358c2cba4a036c8284ec74bc32a70f7757d64abc4d65c87c629a63f", - "review_fingerprint": "e4d0d48eb358c2cba4a036c8284ec74bc32a70f7757d64abc4d65c87c629a63f", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_codex_transform.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c2181ffc7a36166108c4d25c7c27d87081c19dc07543a4ae84c6f3dfd46f7fb9", - "review_fingerprint": "c2181ffc7a36166108c4d25c7c27d87081c19dc07543a4ae84c6f3dfd46f7fb9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Codex OAuth 请求变换核心(1994 行):模型归一映射、store=false/stream=true 收口、不支持字段剥离、legacy functions/function_call 迁移、工具与 tool_choice 归一(allowed_tools 保留不降级)、system→developer/instructions 提升、call_id 形态与 64 字符压缩配对、reasoning item 保 encrypted_content 剥 rs_* id 并回填 summary(#1957)、图片桥指令/Spark 图片禁用、JSON schema 归一。下游 delta:新增显式 reasoning-effort 别名解析(仅识别已知 OpenAI 模型 + effort 后缀,openai/ 命名空间之外不解释;OAuth 解码路径、raw 字节 materialize、API Key 上游归一三处同源)、raw 剥图片工具改用 decodeOpenAIJSONUseNumber 保数值精度、normalizeOpenAIResponsesImageOnlyModelWithModel 供 Cindy 映射前用原始模型名、新增 ErrCindyResponsesImageToolModelNotFound 哨兵。通用网关协议变换,静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: resolveOpenAIModelReasoningAlias/isKnownOpenAIReasoningAliasEffort/materializeOpenAIModelReasoningEffort/applyOpenAIModelReasoningAlias (L626-738) + wired into applyCodexOAuthTransformWithOptions (L178) and normalizeOpenAIModelForUpstream API-key branch (L1362-1366); decodeOpenAIJSONUseNumber in stripOpenAIImageGenerationToolsFromRawPayload (L965); WithModel variant (L1276-1280); ErrCindy... sentinel (L16).", - "Alias safety: explicit-field wins (reasoning.effort/reasoning_effort presence short-circuits, L681), no family remapping (gpt-5-low stays gpt-5), gpt-5.1-codex-max excluded, double-effort suffixes rejected (L648-650).", - "Inherited note: applyInstructions keeps its unused isCodexCLI parameter exactly as upstream (verified via git show aea725f...); not downstream debris.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_transform_additions_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6a0338a26529dfcbcb3eef1e50228a1d9c9fa1ead431f9e03abda9f9c014d200", - "review_fingerprint": "6a0338a26529dfcbcb3eef1e50228a1d9c9fa1ead431f9e03abda9f9c014d200", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "变换补充测试:ensureCodexReasoningInclude 幂等加法、applyCodexClientMetadata 用真实 device_id 注入且不伪造不覆盖、按模型选择 base instructions。下游 delta 新增 TestRequestIntegrityCanonicalizationCases:compareRequestIntegrity(openai_request_integrity_semantics.go,另一切片)把已记录的无损 Codex 兼容变换(字符串 input 展开、保留名别名、namespace 拍平、Lite additional_tools 迁移、账号模型映射、服务端 instructions 后缀、图片桥注入)归一后判等,真实丢失/改写(丢 input 项、丢工具、改 previous_response_id、丢加密推理项)报告首个差异字段。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: only the new TestRequestIntegrityCanonicalizationCases (L71-150); earlier three tests unchanged.", - "Statically read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_codex_transform_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "81ace3dd91414acacfad3f3fba226bf2f44195827dcfb5b4cbccc54cadf3b2d7", - "review_fingerprint": "81ace3dd91414acacfad3f3fba226bf2f44195827dcfb5b4cbccc54cadf3b2d7", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_codex_turn_state.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d5c860bd9335462971635d92e60666740b6c78bddc9e5bc98c5a6a45b50a5467", - "review_fingerprint": "d5c860bd9335462971635d92e60666740b6c78bddc9e5bc98c5a6a45b50a5467", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "x-codex-turn-state 回合状态血统机制:溯源表记录(API Key+客户端会话 → 铸造账号,TTL),中继/暂存提交两条路径共享,出站守卫剥离跨账号回带。下游 delta 是防检测正确性修复:守卫从『只剥已知异账号』翻转为 fail closed(无溯源、过期、缺会话标识、缺账号一律剥离,只有可证明由当前账号铸造才保留);空 state 的成功提交清除旧 provenance(relay 与 staged 两侧);新增 commitOpenAIWSSessionTurnState 在响应提交边界同步 WS 回退状态存储(空 state 使所有旧 owner 失效)。溯源表每 256 次写入全量清扫 + TTL,有界。票据注入属 codex-runtime 插件(openai_codex_ticket.go,另一切片),此处只做回显守卫——无第二执行者。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: fail-closed guard rewrite (L161-196), clearOpenAICodexTurnStateProvenance added and called from relay/staged empty-state paths (L56, L92, L121-128), new commitOpenAIWSSessionTurnState with OpenAIWSStateStore Bind/DeleteSessionTurnState (L134-155).", - "Callers: relay path (openai passthrough response headers), staged first-output guard, WS forwarder; seed shares extractClientSessionID with fingerprint thread derivation (L32-41).", - "Bounded state: sweepOpenAICodexTurnStateOrigins every 256 writes + lazy expiry on read (L188-192, L200-212).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_codex_turn_state_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cf1f8219248d6eb81b57c6c21cecdff3d2124b9cfee836b9aff29ee7f1d463af", - "review_fingerprint": "cf1f8219248d6eb81b57c6c21cecdff3d2124b9cfee836b9aff29ee7f1d463af", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "turn-state 血统机制的单测:seed 构造(连字符优先/无会话不跟踪)、中继写头+记录溯源、上游缺失时清残留值与 provenance、暂存阶段不记录溯源而提交时才记录(被 failover 丢弃的 attempt 不污染)、守卫矩阵(同账号保留;异账号/无溯源/过期/无会话/无账号一律剥离——下游把后四类从保留翻转为剥离)、清扫剪除过期项、透传响应头强制中继与清除 turn-state、beta features 会话级注入契约(OAuth 每请求带 remote_compaction_v2、客户端显式声明不改写、native v2 实锤强制、WS 与 HTTP 同形态)。测试静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S17-svc-openai-codex-1-review.json", - "Delta vs aea725f: TestNoteStagedOpenAICodexTurnStateCommitted_NoopWithoutState renamed ..._ClearsProvenanceWithoutState with cleared-provenance asserts (L140-160); guard subtests flipped to require.Empty for unknown/expired/no-seed/missing-account (L196-232); relay-clear test extended to assert provenance deletion (L65-80).", - "Beta-features and WS-parity tests (L290-419) prove session-level header contract against buildOpenAIWSHeaders (core gateway).", - "Statically read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_compact_fallback_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "00c3b9b060e07321bcbff2ee44e273d398c9218cc5ec170e5844694759da6a38", - "review_fingerprint": "00c3b9b060e07321bcbff2ee44e273d398c9218cc5ec170e5844694759da6a38", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "compact 模型回退(context_length_exceeded 时换 compact 模型重试一次)的行为测试:要求显式 compact 触发(/compact 路径或 compaction_trigger)、账号级 compact_model_mapping 优先于全局配置、同模型/业务性失败不回退、单次回退防递归、HTTP 与 SSE(输出前)失败都可回退、ops 事件(retry/compact_model_fallback)带托管代理归属、第二次失败走标准错误路径。下游相对上游 aea725f 仅 1 处 3 行:forwardOpenAIPassthrough 调用签名少了一个 nil 参数(下游重构删参的适配),断言语义与上游完全一致,故记 reference。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:仅 L499-L500 调用签名变化(去掉一个 nil 实参),无断言/fixture 变化", - "被测:prepareOpenAICompactFallbackRetry/resolveOpenAICompactFallbackModel/isOpenAICompactModelFailure 与 Forward 的 compact 回退分支(openai_compact_fallback.go,不在本切片)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_compact_model_mapping_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b59a11e5f503dabf3c4c556fe939c7c0bb0dff7641f9b49a6316924ebb7a1d15", - "review_fingerprint": "b59a11e5f503dabf3c4c556fe939c7c0bb0dff7641f9b49a6316924ebb7a1d15", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "compact 专用模型映射(compact_model_mapping 仅对 /responses/compact 生效、优先于 model_mapping、passthrough 也生效且客户端回显原模型)与 compaction_trigger 归一(历史清理后触发器移到末位)的测试。下游相对上游改写一例:APIKey compact 请求不再把 input 清洗成单条 message(旧名 SanitizesStatelessReplayAfterStoreWasDropped),改为完整保留 3 项 input(含 reasoning 与 item_reference 的服务端引用)原样出站,仅仍剥离 parallel_tool_calls——证明下游取消了对 APIKey compact 的 stateless 重写、保留先前 store 引用这一行为修正。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:测试改名并把断言从 input.#==1/仅 message 改为 input.#==3 且 JSONEq 原始 input(L61-L98);其余四例与上游一致", - "被测:Forward 的 compact 路径模型解析与 input 处理(openai_compact_* 源文件),upstream fixture 经 httpUpstreamRecorder", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_compact_stream_bridge.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "80706cca8e27476b46176a810af5ea601c0ad9c3c1729671edc6ec0f7ed442ec", - "review_fingerprint": "80706cca8e27476b46176a810af5ea601c0ad9c3c1729671edc6ec0f7ed442ec", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "body-signal compact(Codex remote compact v2)的 SSE 合成桥:unary /responses/compact 的最终 JSON 按客户端消费协议合成 response.output_item.done*+response.completed 帧(补 id/剔除不可解析 usage/单调 sequence_number/created_at 必填),心跳已提交 200 时非 2xx 降级为 response.failed 终止事件并标记 ops 流内错误。下游相对上游 +61/-24:新增错误上报形态 writeOpenAICompactSSEBridgeResult / writeOpenAICompactSSEFailure(Message)Result——把 Writer.Write 的错误与短写(io.ErrShortWrite)传回网关提交边界,使『已处理』不再等同『已送达』,供上层判定终端投递失败。协议合成属核心网关机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:L59-L104 Result 变体与写错/短写检查、L106-L163 失败写回改为返回 error 并显式组帧;合成逻辑 buildOpenAICompactSSEPayload L172-L244 与 usage 校验 L246-L256 未变", - "调用链:MarkOpenAICompactClientStream 由 handler 在 body-signal 提升时设置;写回方为网关 HTTP 提交边界(openai_gateway_*),心跳协作 StopOpenAICompactSSEKeepaliveCommitted(openai_compact_sse_keepalive.go)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_compat_host_observation_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "31fa4a0d08c998d0960c5d48d4e9e0f66928e37d287c13f66c5bbcfbc863f3c3", - "review_fingerprint": "31fa4a0d08c998d0960c5d48d4e9e0f66928e37d287c13f66c5bbcfbc863f3c3", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "全文复核250行fake实际CC/Messages Forward场景:dispatch前最终wire模型、buffer/stream completed缺usage只告警一次(同时校验sampler total)、shadow只通知父ID且不复制凭据或多发请求;失败/incomplete与已有usage不计completed告警,恢复链仅最终成功计一次。全局fixture非并行且恢复registry/采样控制,不启动quota worker。", - "evidence": [ - "artifacts/evidence/v027-astra-compat-host-observation-review.json", - "Parent read the entire fixture and matched current SHA; only the report-specific targeted commands were run." - ] - }, - { - "path": "backend/internal/service/openai_compat_model.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f7e85fe896997b55d36e93888c479969a40a35ac8f32048c94cd936246795a66", - "review_fingerprint": "f7e85fe896997b55d36e93888c479969a40a35ac8f32048c94cd936246795a66", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Anthropic 转 OpenAI 兼容桥的模型别名归一(77 行)。下游相对上游:删除本地 gpt- 前缀后缀解析器与 openAIReasoningEffortToClaudeOutputEffort(xhigh 曾折叠为 Anthropic max),改为统一调用共享的 resolveOpenAIModelReasoningAlias(openai_codex_transform.go L626)——消除了一处别名解析的重复执行体;别名派生的 effort 现按原值保留(xhigh 与 max 在新模型上是不同档位,注释明确不再经 Anthropic max 往返丢失意图);openAICompatAnthropicReasoningEffort 仅当最终上游模型 supportsOpenAIReasoningEffortMax(openai_gateway_request_body.go L2397)才保留 max,否则回落转换值。与记忆中 #142『GPT effort 档位保真』一致。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:-40 行本地解析器/effort 折叠函数,+效仿共享别名 L54-L59;effort 保真注释与 supportsOpenAIReasoningEffortMax 门 L66-L77", - "调用链:ForwardAsAnthropic 入口 applyOpenAICompatModelNormalization -> 共享 resolveOpenAIModelReasoningAlias;最终 effort 由 openAICompatAnthropicReasoningEffort 在上游模型确定后复核", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_compat_model_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "380d2e7631e54edbc6991cebf5eb444181f7f0deb392e17b4b3d43ada8ad478d", - "review_fingerprint": "380d2e7631e54edbc6991cebf5eb444181f7f0deb392e17b4b3d43ada8ad478d", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "ForwardAsAnthropic(Anthropic 转 Responses 桥)的大型行为测试(2358 行,下游 +73/-28)。全文覆盖:模型别名归一与 effort 派生、GPT-5.6/Astra 的 max 保留 vs 旧模型折叠 xhigh、prompt_cache_key 注入/自动派生(anthropic-digest-/anthropic-metadata- 前缀)与跨轮稳定、codex 兼容模型的历史裁剪与 todo-guard 注入、previous_response_id 续接(严格识别 not-available、一次性回放全量历史、WS v2 不支持则永久禁用续接、OAuth 不续接)、x-codex-turn-state 复用、终端事件缺失的三分类(输出前 failover / 输出后仅 ops / 客户端断开不计)、缓冲聚合 Content-Type 覆盖、客户端断开后仍收割 usage、上游请求不随客户端取消。下游 delta 证明三组核心修正:(1) xhigh 不再折叠为 max(断言 L104);(2) 会话头治理——session_id 下划线头断言全部改为连字符 session-id,新增入站连字符会话头只作用域改写一次、不被 cache-key 回退覆盖且下划线头不出站(L1071-L1111);(3) 出站 UA 从常量 codexCLIUserAgent 改为账号作用域 resolveCodexOutboundIdentityForAccount。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:uuid 导入、L104 xhigh 断言、新增 TestForwardAsAnthropic_KeepsInboundHyphenSessionHeaderOverCacheKeyFallback(+44 行)、约 10 处 session_id 改 session-id、4 处 UA 断言改 resolveCodexOutboundIdentityForAccount", - "被测:ForwardAsAnthropic/handleAnthropicBufferedStreamingResponse/bindOpenAICompatSessionResponseID/disableOpenAICompatSessionContinuation/isOpenAICompatPreviousResponse{NotFound,Unsupported};helper openAICompatSSECompletedResponse L1550", - "未执行测试,不主张真实 Codex 客户端行为。" - ] - }, - { - "path": "backend/internal/service/openai_compat_reasoning_fidelity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "abd4bde69ff42c885689b536790ff17543d59641d5c08cae322ca220ce270387", - "review_fingerprint": "abd4bde69ff42c885689b536790ff17543d59641d5c08cae322ca220ce270387", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(73 行),证明 effort 档位保真规则(对应 #142 GPT 档位保留决策):openAICompatAnthropicReasoningEffort 仅当最终上游模型支持独立 max 档(gpt-6-astra/gpt-5.6 系)才保留请求的 max,旧模型(gpt-5.2)与未知目的地回落转换值 xhigh,且不改写请求对象;别名表——sol-xhigh 保 xhigh、astra-max 保 max、-none 不被丢弃、minimal 与 none 区分、显式 output_config 覆盖别名、gpt-5.1-codex-max 的 max 是模型名不是档位、未知/非 OpenAI 模型不改写,并经 AnthropicToResponses 全链路断言 wire 上的 model 与 reasoning.effort。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta(git ls-tree aea725f 无此路径);两组表驱动:档位保真 L12-L34、别名与全链路 L36-L73", - "被测:openAICompatAnthropicReasoningEffort/applyOpenAICompatModelNormalization(openai_compat_model.go 本切片)与 supportsOpenAIReasoningEffortMax(openai_gateway_request_body.go L2397)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_continuation_diagnostic.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "b868febdf737095d1f47ca4961834c2688bde2b6d33799f1ad55325bee2ab990", - "review_fingerprint": "b868febdf737095d1f47ca4961834c2688bde2b6d33799f1ad55325bee2ab990", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增文件(456 行)。续接类 400 失败(previous_response_not_found/invalid_encrypted_content/thinking_signature_invalid/request_validation 等)的隐私保全诊断结构:对入站与实际出线请求分别产出指纹视图(prompt_cache/instructions/previous_response/会话头/client_metadata.session 只记 kind+字节数+字符数+sha256,绝不留明文),input 历史只记形状计数(消息/推理/压缩/引用/调用配对、重复与孤儿 call_id、密文数与序列摘要,上限 1024 项);错误 type/code 仅白名单枚举可留值、param 须匹配协议字段正则(<=96 字符)、message 只留固定 hints;sanitize 再过一遍白名单并强制序列化不超过 6KB,超限即丢弃整个诊断——评论明确该类型化字段不允许任何生产者夹带任意文本进 ops 队列。wire 来源优先取 recovery 冻结快照(frozen_request),GetBody 缺失时降级 prepared_fallback 并标记 inspection_limited,绝不消费活动请求体。纯观测,不改转发行为。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta;锚点:指纹 L150-L173、请求视图 L183-L201、历史形状 L210-L287、param 正则 L289、错误枚举白名单 L291-L299、hints L301-L304、分类白名单 L349-L358、sanitize+6KB 上限 L362-L444", - "调用链:openai_gateway_forward.go/openai_gateway_passthrough.go 构造 -> OpsUpstreamErrorEvent.ContinuationDiagnostic -> SanitizeOpsUpstreamErrorsForQueue 入 ops 队列;recovery 快照来自 openai_reasoning_recovery.go", - "未执行测试;不主张 ops 看板展示行为。" - ] - }, - { - "path": "backend/internal/service/openai_continuation_diagnostic_forward_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1f466aeaa800e815b1a771227af1b5d91f6e2df18d227a106e4f1c2525b76ec6", - "review_fingerprint": "1f466aeaa800e815b1a771227af1b5d91f6e2df18d227a106e4f1c2525b76ec6", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(211 行)。9 组表驱动(native/passthrough x stream/nonstream x 显式续接错误/泛化 400/缺参校验)证明:Forward 在终止性 400/502 上返回 request-scoped 错误(continuation_state 或 request_rejected,Scope=Request、NextAccountStop、不惩罚健康、不换号),诊断只附着到既有 ops 事件(事件数仍为 1、Detail 不变、不触发重试),客户端只见脱敏 message(上游私有校验文案 private-validation-message-51937 不出现在事件 JSON),wire 侧取 frozen_request 快照且 GetBody 保持 nil(禁止透明重放),prompt_cache 指纹与实际出线体一致,历史形状计数正确。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta;断言锚点:终止语义 L150-L173、事件附着与脱敏 L180-L208、frozen_request/GetBody=nil L195-L198", - "被测:Forward 的 continuation 诊断挂载(openai_gateway_forward.go/passthrough.go)与 buildOpenAIContinuationDiagnostic(本切片)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_continuation_diagnostic_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5298a05ad44bf59825a6eb79aa5942c545b4abd76f1b9db0bca8bb7cd341982a", - "review_fingerprint": "5298a05ad44bf59825a6eb79aa5942c545b4abd76f1b9db0bca8bb7cd341982a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(515 行),锁定诊断结构的隐私契约与资源边界:白名单枚举/协议 param 才留值(namespace 带私有后缀或 query 即只留指纹)、非 JSON 错误只留完整指纹+固定 hints、api_key/bearer/email/URL/CRLF/超长 Unicode/对象/数组等注入样本一律无明文、未知 classification 落 unclassified;结构测试证明确定性输出、incoming/wire 双视图指纹、13 项历史形状计数(含重复/孤儿 call_id)、missing/null/空串三态可区分、诊断不改字节/头/不消费活动 body;资源边界:1024 项扫描上限+scan_limited、8MB 体检查上限(保留 ContentLength 真实大小)、克隆失败不回退消费活动体;ops 队列往返:SanitizeOpsUpstreamErrorsForQueue 释放指针保留序列化证据、旧事件超出 body 窗口丢弃诊断、request_rejected 与 legacy 分类语义在存储往返中不变、队列 JSON 无明文。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta;锚点:隐私矩阵 L75-L213、结构/不可变 L215-L333、资源边界 L351-L402、ops 队列往返 L404-L515(opsUpstreamErrorsBodyWindow 窗口)", - "被测:buildOpenAIContinuationDiagnostic/sanitizeOpenAIContinuationDiagnostic(本切片)、SanitizeOpsUpstreamErrorsForQueue/ParseOpsUpstreamErrors(ops 队列层)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_cyber_policy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "037ffd46c26001c1b18da2d9ce7fb60dc4f3e831d9ae11ff65b154cf221d80e9", - "review_fingerprint": "037ffd46c26001c1b18da2d9ce7fb60dc4f3e831d9ae11ff65b154cf221d80e9", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "cyber_policy 标记与识别的单元测试:Mark/Get/first-wins/nil 安全/Clear 后可重标(WS 每轮生命周期),detectOpenAICyberPolicy 只认 error.code=cyber_policy(含 response 包装、大小写与空白容差),content_policy 与含 cyber 字样的 safety message 不误判。下游相对上游仅把一行大小写用例拆成三行(不同大小写、全大写、前后空白),断言语义不变,故记 reference。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:仅 L72-L74 用例行拆分(case-insensitive 改为 different case/uppercase/surrounding whitespace 三行)", - "被测:MarkOpsCyberPolicy/GetOpsCyberPolicy/ClearOpsCyberPolicy/detectOpenAICyberPolicy(openai_cyber_policy.go,上游已有)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_cyber_session_block.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "556cf04686ec641a0597a86d24b96f2cf308cd58351b7b4366e607dc9d15567a", - "review_fingerprint": "556cf04686ec641a0597a86d24b96f2cf308cd58351b7b4366e607dc9d15567a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "cyber 会话屏蔽(命中 cyber_policy 后按会话/转写前缀拦截后续请求)的宿主机制:显式会话键(session_id/prompt_cache_key,按 apiKey 隔离哈希)、转写键(须含模型产出历史)、粗粒度来源 scope(apiKey+IP+归一化 UA)作为免解析门、scope 激活且转写键超上限时 fail-closed(返回 overflow 哨兵键、不发无界 MGET)、其余失败一律 fail-open;存储经类型断言探测 GatewayCache(注释明示装饰器包装会静默降级);开关与 TTL 经 SettingService 进程内缓存。下游相对上游 +22:恢复 v0.1.179 兼容包装 CyberSessionBlockKey(供未迁移到转写查找的调用方)与新增 IsCyberSessionBlocked(key) 单键查询助手,其余与上游一致。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:L32-L36 legacy 包装、L171-L185 IsCyberSessionBlocked;核心逻辑(scope 门 L144-L158、overflow fail-closed L153-L158)与上游一致", - "调用链:命中写入 MarkCyberSessionBlocked(cyber 命中后)、入场查 FindCyberSessionBlockedForRequest;键派生 deriveOpenAICyberTranscriptBlockKeys(openai_cyber_transcript.go);存储 repository gatewayCache", - "未执行测试;不主张 Redis 行为。" - ] - }, - { - "path": "backend/internal/service/openai_cyber_session_block_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "53bd745fdcbf904d12f79c94a1a5f60d9f557efb603849d82d5597010980772a", - "review_fingerprint": "53bd745fdcbf904d12f79c94a1a5f60d9f557efb603849d82d5597010980772a", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "cyber 会话屏蔽测试:显式键的 apiKey 隔离与稳定性(session_id/conversation_id/prompt_cache_key/WS response.create)、转写键须有模型产出历史且续写可命中、查找键有界且保序(最老保留者与全量键位置)、fail-open(nil service/空键)、combo cache+store 往返、scope 门控转写匹配(UA 版本归一)、scope 激活下超限 fail-closed 且零次存储查询、ScopeKey 归一化。下游相对上游仅 +3 行:测试 stub 补 DeleteSessionAccountIDIfMatches 以满足扩展后的 GatewayCache 接口,断言语义不变,故记 reference。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:仅 L197-L199 stub 新方法;其余 fixture(fakeCyberBlockStore/fakeSettingRepo/comboCacheAndStore)与用例与上游一致", - "被测:openai_cyber_session_block.go(本切片)与 SettingService.GetCyberSessionBlockRuntime", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_embeddings.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "453ee9683f3bca8f5d76334ac237a1fd0cd969659cc3363610f001097892ea64", - "review_fingerprint": "453ee9683f3bca8f5d76334ac237a1fd0cd969659cc3363610f001097892ea64", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI /v1/embeddings 转发(APIKey 协议,255 行)。下游相对上游 aea725f +33/-14:入口先 CaptureCindyPricingContext(供应商策略不可用即 503 并返回错误);模型解析改 resolveOpenAIForwardModelContext——Cindy 账号经目录快照映射(openai_model_mapping.go L29-L41),非 Cindy 走原 resolveOpenAIForwardModel;上游传输错误从『写 502+记 request_error 事件』改为委托 handleOpenAIUpstreamTransportError(返回可重放的类型化 failover,不提前提交客户端响应);新增 Cindy model-not-supported 结构化 failover 分支,注释明确其他 embeddings failover 保留历史空头形态。多模态 image_tokens 拆分与既有 URL 构造/头透传保持上游语义。按 Codex 冻结说明审查 63a98c8cc 之后的当前磁盘字节(切片旧 sha d37fe8ed 已过期)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:L27-L32(pricing context)、L41-L44(模型策略上下文)、L104-L107(传输错误委托)、L140-L146(Cindy 能力 failover);usage 提取 L209-L251 与上游一致", - "调用链:handler embeddings 入口 -> ForwardEmbeddings -> doOpenAIUpstream;Cindy 映射经 LoadCindyCatalogSnapshot(插件目录快照)", - "sha256 由本次审查自算并绑定 post-63a98c8cc 版本;未执行测试或真实请求。" - ] - }, - { - "path": "backend/internal/service/openai_embeddings_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d2c47a8bc86df56f06a2254d02151418f205c4c231acbe60f9fc297c6e96b9e5", - "review_fingerprint": "d2c47a8bc86df56f06a2254d02151418f205c4c231acbe60f9fc297c6e96b9e5", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "embeddings 转发测试。上游已有:URL 构造(bare/v1/已含 embeddings/第三方 v4 路径)、APIKey 透传记录 usage 与批量 input、access-state 403 类型化 failover、非 access failover 保留历史空形态(429)。下游 +29 行新增 TestForwardEmbeddings_TransportFailureReturnsReplayableFailoverWithoutWritingResponse:传输层失败(connection reset)现在返回 OpenAITransientTransportFailureReason 的可重放 failover 且不向客户端写任何字节——证明 openai_embeddings.go 下游把传输错误从提前写 502 改为类型化换号这一修正。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:仅 +TestForwardEmbeddings_TransportFailure...(L19-L46)与 errors 导入;其余四个用例与上游一致", - "被测:ForwardEmbeddings(本切片,frozen 版)与 handleOpenAIUpstreamTransportError", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_encrypted_content_lineage_legacy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ca6d2da26c2ff33fb1c20524e7c81a75b987f8cf10c72414dfa4cc789c6e2db6", - "review_fingerprint": "ca6d2da26c2ff33fb1c20524e7c81a75b987f8cf10c72414dfa4cc789c6e2db6", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增的 _test.go 文件(258 行)但不含任何 Test 函数:保留『失效密文 lineage 剥离』的历史实现(摘要收集、按摘要剥离 map/replay 项/raw payload、零成本命中探测)仅作回归 fixture。文件头注释明确:生产转发路径不再包含任何抹除状态的 lineage 操作,新请求必须保留原始状态——即该业务行为已从生产移除,代码只为 openai_encrypted_content_lineage_test.go 与 openai_native_fidelity_test.go 的回归断言保留(rg 确认仅测试文件引用)。剥离语义与 sanitizeEncryptedReasoningInputItem 对齐、遵守 replay 所有权不变式(零拷贝视图、原正文不改)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta;锚点:类型白名单 L31-L38、摘要收集 L42-L71、map 剥离 L77-L140、replay 项剥离 L181-L237、raw 探测+改写 L241-L257", - "引用面:rg --no-config 显示仅 openai_encrypted_content_lineage_test.go 与 openai_native_fidelity_test.go 使用这些助手;生产源码零引用(test-only 编译)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_failover_cached_body_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bdc941d791ba1a9a8dbe4f09b60728ea2685f27c1d4288d68819af7667485643", - "review_fingerprint": "bdc941d791ba1a9a8dbe4f09b60728ea2685f27c1d4288d68819af7667485643", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "failover 换号时请求体缓存语义的回归测试:换号后按新账号的 model_mapping 重解析原始 body(四组映射组合,legacy 上下文缓存 openai_parsed_request_body 被忽略)、handleFailoverSideEffects 不重读响应体(panicOnReadCloser 证明)、getOpenAIRequestBodyMap 忽略旧缓存。下游相对上游仅 -1 行:删除对 shouldRetryOpenAIOAuth429OnSameAccount 的断言(该助手在下游被重构移除/改名),其余断言与上游一致,故记 reference。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:仅 L131 处删除一行 require.True(shouldRetryOpenAIOAuth429OnSameAccount...)", - "被测:Forward 的 body 重解析、handleFailoverSideEffects、getOpenAIRequestBodyMap(openai_gateway 系列,上游已有)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_fast_policy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2622942fea0dd891ffea0ebbb9fa164f4e8ec69625c1c4bf9ca026784867f86b", - "review_fingerprint": "2622942fea0dd891ffea0ebbb9fa164f4e8ec69625c1c4bf9ca026784867f86b", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "OpenAI fast/service_tier 策略测试(585 行):默认无规则不改写、block 带消息、scope 过滤 OAuth、用户白名单规则覆盖全局、force_priority 注入/改写各 tier、missing-tier 仅 force 规则注入、分组 ForceOpenAIFast(需 Hydrated、只作用于 OpenAI 账号与受支持分组平台、全局 filter 仍权威)、官方 tier 默认透传、all+filter 全剥离、未知 tier 由前置归一化剥离、设置校验(非法 action/tier/非正与重复 UserIDs 拒绝、合法三规则持久化往返)。下游相对上游仅 stub 内变量改名(result 改 values),零语义变化,故记 reference。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:仅 GetMultiple stub 的变量名(L38-L46),无断言变化", - "被测:evaluateOpenAIFastPolicy/applyOpenAIFastPolicyToBody/SetOpenAIFastPolicySettings(openai_fast_policy.go,上游已有)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_403_reset_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c1b7ee90fd0850b0579be0baf7f2515551c339b96b9a2d37000cf2afc04c900c", - "review_fingerprint": "c1b7ee90fd0850b0579be0baf7f2515551c339b96b9a2d37000cf2afc04c900c", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "OpenAI 网关 RecordUsage 的三个单元测试。上游原有用例证明 PlatformOpenAI 账号零用量结果仍调用 ResetOpenAI403Count(777) 并写入一条用量行;下游新增两例证明:具备规范 Cindy 供应商身份的账号在 RecordUsage 成功路径上向 CindyHealthCoordinator.ObserveCindyHealthSuccess 上报实际 account.ID(778),而 CyberBlocked=true 的 cyber 用量行不触发该上报。被测对象是宿主 openai_gateway_usage.go L157-L160 对 Cindy 健康协调器接口的调用胶水(接口定义于 cindy_health.go L108,响应分类经 plugin_cindy.go classifyCindyProviderResponse 委托插件),测试证明的是宿主到 cindy 域的桥接行为而非计价或目录规则。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "下游新增 TestOpenAIGatewayServiceRecordUsage_ReportsCindyRecovery L50-L73 与 _CyberLogIsNotCindyRecovery L75-L98(diff vs aea725f 为 +50 行);stub cindyHealthCoordinatorRecorder 与 newFirstClassCindyRateLimitAccount 定义于 cindy_balance_shared_test.go L26/L194", - "调用链:OpenAIGatewayService.RecordUsage(openai_gateway_usage.go L149) → !input.CyberBlocked && hasCanonicalCindyProviderIdentity(provider_identity.go L107) → s.cindyHealth.ObserveCindyHealthSuccess;协调器由 wire.go L136/L139 经 SetCindyHealthCoordinator 注入", - "未执行测试、未构建;不主张 CindyHealthService 本体(不在本切片)的归属,也不主张其与 plugins/cindy-provider/catalog/health.go ClassifyResponse 的分工是否完备。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_anthropic_native_pump_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ac188ad0bf401ae2e4b162d66f6ef8d6dc69249653501e243e7d6a99bfe53072", - "review_fingerprint": "ac188ad0bf401ae2e4b162d66f6ef8d6dc69249653501e243e7d6a99bfe53072", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "国产供应商 Anthropic 协议反向路径(CC×anthropic、Responses×anthropic)的读间隔超时与转换回归测试:断言 newAnthropicNativeLinePump 在无数据时按 interval 报 'stream data interval timeout' 且收到数据后重置计时;四条 handle*FromNativeAnthropic 在上游挂住 SSE 时于 5 秒内返回并带回累计 usage(缓冲路径回写 502);happy path 仍转换出 'Hello'、data: [DONE] 与 usage 10/5;tool_use 的 input_json_delta 在 CC 与 Responses 缓冲输出中都拼成合法 JSON arguments。下游相对上游 aea725f 仅在 4 处 t.Fatalf(res==nil) 之后补 return(nil 解引用防护),断言语义与上游一致,主体为上游既有测试,故记 reference。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f:仅 L152/L203/L231/L264 各新增一行 return,无断言或 fixture 变化", - "被测函数:newAnthropicNativeLinePump(openai_gateway_anthropic_native_pump.go L43)、handleCC{Streaming,Buffered}FromNativeAnthropic(本切片 openai_gateway_chat_completions_anthropic_native.go L298/L146)、handleResponses{Streaming,Buffered}FromNativeAnthropic(openai_gateway_responses_anthropic_native.go L304/L148)", - "未执行测试、未构建;不主张 gateway.stream_data_interval_timeout 生产取值。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_apikey_item_id_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6099a7a6ca0afe8f3383601bfac7dc1d22ff2a59581f011d55f0279a130c7160", - "review_fingerprint": "6099a7a6ca0afe8f3383601bfac7dc1d22ff2a59581f011d55f0279a130c7160", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Responses 输入项 id 清洗与 WS 兼容体归一化的单元测试:断言 item_*/错误前缀 id 被剥除而 msg_/fc_/ctc_/tsc_/rs_/ws_ 合法前缀保留、OAuth/SetupToken passthrough 命中 chatgpt.com codex/responses 端点、SetupToken 旧路径把 reasoning.mode=pro 变为 effort=max 且 store=false、清洗分配随输入项线性增长(200 项 < 20 项 ×30)、WS 兼容体保留 item_reference 不透明引用且二次归一化幂等。下游相对上游唯一改动是 SetupToken 旧路径用例 L137-L159:把「孤儿 function_call_output 被丢弃仅剩 1 项」换成「匹配 call_id 的 custom_tool_call_output 保留、共 2 项且 output 原样」,即该用例不再证明孤儿输出过滤而证明匹配输出在清洗+变换链中存活;孤儿过滤逻辑本体在 openai_gateway_forward.go 调用的 sanitizeOpenAIResponsesOrphanToolOutputs(openai_responses_input_compat.go L13)。文件主体为上游测试,静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f:L145 fixture 与 L158-L159 断言变更(共 5 行),其余 6 个用例与上游一致", - "调用链:svc.Forward → shouldStripOpenAIResponsesInputItemID / sanitizeOpenAIResponsesInputItemIDs(openai_responses_item_id.go L48/L65)、normalizeOpenAIResponsesWebSocketCompatibilityBody(openai_gateway_request_body.go L1295);测试构造复用 openai_image_generation_controls_test.go L780-L822 与 httpUpstreamRecorder(openai_oauth_passthrough_test.go L32)", - "未执行测试;未验证 OpenAI 上游对 rs 前缀 reasoning id 的真实拒绝行为(注释引 #5410)。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_cc_pipeline.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "acc37c6083469699dc64c46b5b1a4ff2ad8d15ecff304af1e3f5482f2177979f", - "review_fingerprint": "acc37c6083469699dc64c46b5b1a4ff2ad8d15ecff304af1e3f5482f2177979f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "三条 CC forwarder 共用的 HTTP 管线与 SSE 循环骨架:scanner 构造、幂等流式响应头写入、上游错误体读取回卷、>=400 failover 判定、CC 上游请求发送、scanCCStream 读循环与非流式 JSON 读取。下游相对上游:readOpenAIUpstreamError 增加 gin 参数并把 body 回卷为 rewoundOpenAIUpstreamErrorBody(原始 wire 字节仅供 Cindy 分类,其余读者只见 rewriteBusinessSystemPromptJSONForAnyRequest 脱敏后的体);failoverOpenAIUpstreamHTTPError 前置 isOpenAIRequestScopedSafetyRejection→markOpenAICyberPolicyFromResponse 与 handleCindyBalanceHTTPFailover(后者经 ClassifyCindyBalanceInsufficient→plugin_cindy.go classifyCindyProviderResponse 走 extensionv1 调用插件,非宿主重实现),pool 重试判定改用 openAIHTTPPoolRetryable;scanCCStream 新增账号可变参、decodeCCStreamChunk(error 信封/畸形 chunk/异常 finish_reason 一律 502 ccStreamProtocolFailure)、FinishReason 追踪、缺 finish_reason 判 upstream_incomplete_response、客户端 ctx 取消带出;发送改走 doOpenAICodexUpstream。均属宿主通用转发机制;DeepSeek reasoning_content 占位是 OpenAI 兼容上游协议兼容。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f(约 140 行):L66-L88 rewoundOpenAIUpstreamErrorBody 与 readOpenAIUpstreamError(resp,c)、L101-L118 安全拒绝/Cindy 余额前置与 body 重置、L165 openAIHTTPPoolRetryable、L265 doOpenAICodexUpstream、L297-L310/L333-L367 scanCCStream 改造、L371-L410 新增 ccStreamProtocolFailure 与 decodeCCStreamChunk", - "调用链:handleCindyBalanceHTTPFailover(openai_gateway_upstream_errors.go L684) → ClassifyCindyBalanceInsufficient(cindy_balance.go L253) → classifyCindyProviderResponse(plugin_cindy.go L23);ensureDeepSeekChatReasoningPlaceholders(openai_gateway_responses_chat_fallback.go L533);调用方为 raw CC 直转与两条 CC 回退路径", - "观察:scanCCStream L312-L351 无读间隔上限且上游 ctx 经 detachUpstreamContext→detachPluginPolicyContext(plugin_operation_context.go L20-L23) 为 WithoutCancel(见 findings,低);未执行测试或构建。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_chat_completions.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9216ef934a0186d1946108a1bd526e81836b2b85cc1b97e522e5183d82f1e3c7", - "review_fingerprint": "9216ef934a0186d1946108a1bd526e81836b2b85cc1b97e522e5183d82f1e3c7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Chat Completions 入站主转发(已按 post-63a98c8cc 冻结版本全文重读,当前磁盘字节 1444 行):CC→Responses 转换、Codex OAuth 变换、fast policy、业务系统提示词、reasoning 重放/恢复循环、流式/缓冲响应转换与错误 failover。下游相对上游 aea725f(约 344 行):入口 CaptureCindyPricingContext(cindy_pricing_snapshot.go L27,经 invokeProcessExtensionCached 调用插件 cindy.pricing 取不可变快照,DisallowUnknownFields+owner 校验,宿主不含定价规则);gin 上下文重放/恢复键清零防跨账号残留;restoreBusinessSystemPromptBeforeConversion 与 applyBusinessSystemPromptForRequest/rewriteBusinessSystemPromptCacheKey;resolveOpenAIForwardModelContext(Cindy 账号经 LoadCindyCatalogSnapshot 用插件目录映射,L101/L247);IsCindyAPIKeyAccount 免费池端点校验(CindyFreePoolModelSupportsEndpoint 亦为插件目录调用);cindyLegacyLaxaLiveUpstreamModel;normalizeCindyManagedPromptCacheKey;fillCodexSessionIdentityHeaders 连字符会话头;decodeOpenAIJSONUseNumber;重放/恢复循环 L501-L580(attemptCtx 逐次取消 + openAIRequestContextReadCloser 把取消挂到 Close、TryRecover/TryRecoverError,配套 cancellation 测试证明);流式 processDataLine 增加 cindyBalanceHTTPResponseTerminalFailover、semanticOutputCommitted 跟踪、pendingReasoningRejection、state.ProtocolError 处理;同时删除上游的 SetOpsUpstreamModel、logOpenAISuccessMissingUsage 与影子账号 notifyOpenAIAutoReset 调用(见 findings,低)。域规则均经插件调用或既有宿主 Codex 助手,无插件逻辑重实现。静态阅读,未执行测试。 复审于 5ce1d85fe(HEAD 49c1e8d83):恢复三处观测钩子——L379-L380 Codex 变换后 SetOpsUpstreamModel(c, upstreamModel);L611-L612 影子账号成功后 notifyOpenAIAutoReset(*account.ParentAccountID)(与上游同位置,仅在 handleErr==nil 且非 OAuth 快照分支时触发一次);L801-L803 缓冲成功(status completed)与 L1243 流式 finalizeStream(按新增 terminalEventType 变量)各调用一次 logOpenAISuccessMissingUsage。后者(openai_v183_compat.go L125-L159)为纯日志:usage 有 token 或终态非 completed/done/[DONE]/json 时直接返回,经采样器 Warn,无状态变更;流式与缓冲分支互斥,无重复通知或计费改动。新增 openai_compat_host_observation_test.go 静态证明:最终模型在发送前记录(上游失败亦然)、缺 usage 每协议×流式恰好 1 次告警、影子成功仅通知父账号 1 次且单次上游请求、恢复流程只记最终成功、失败尝试与 incomplete 不发成功信号。static,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "frozen post-63a98c8cc 版本全文重读:L64-L68 定价捕获、L83-L120 提示词还原与模型策略、L136-L232 路由分流(Grok/OpenCodeGo/adaptive/anthropic/raw-CC)、L344-L377 Codex 变换、L395-L434 fast policy+业务提示词+Cindy 缓存键、L442-L463 会话头、L471-L611 重放/恢复循环与收尾、L664-L797 缓冲响应、L844-L1415 流式响应(interval/keepalive 双 ticker L887-L899/L1378-L1391)", - "宿主→插件委托链:CaptureCindyPricingContext→invokeProcessExtensionCached('cindy.pricing');resolveOpenAIForwardModelContext→LoadCindyCatalogSnapshot;CindyFreePoolModelSupportsEndpoint→queryCindyCatalog(plugin_operation.go invokeProcessExtensionCached);detectCodexClientRestriction/prepareCodexAccountIdentitySource 等 Codex 助手留在宿主,其域归属由对应文件切片判定", - "相对上游删除:SetOpsUpstreamModel(Codex 变换后最终 slug 标注)、logOpenAISuccessMissingUsage(流式+缓冲两处;该函数在 passthrough/response_handling 仍有 6 处调用)、影子账号成功后的 notifyOpenAIAutoReset;记 findings 低", - "本记录绑定 post-63a98c8cc 冻结后的当前磁盘 sha256;未执行测试或构建,无浏览器或生产验证。", - "复审锚点(5ce1d85fe):diff 05e25bdf2..HEAD +10 行(L379-L380、L611-L612、L801-L803、L873、L990、L1243);notifyOpenAIAutoReset(openai_quota_auto_reset.go L777) 仅 service.Notify 轻量信号" - ] - }, - { - "path": "backend/internal/service/openai_gateway_chat_completions_anthropic_native.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "6f7914a925295776dfb2cd940760b694d16d9db262ee36b00e47421e45691b9c", - "review_fingerprint": "6f7914a925295776dfb2cd940760b694d16d9db262ee36b00e47421e45691b9c", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_gateway_chat_completions_cancellation_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "35f86736fe73cf292b9e187ef7eed2a8f1e0780a3113fb7fc8f3eddf9d43da6c", - "review_fingerprint": "35f86736fe73cf292b9e187ef7eed2a8f1e0780a3113fb7fc8f3eddf9d43da6c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "验证 ForwardAsChatCompletions 流式路径的取消语义。上游原有用例证明关闭上游 body 前先取消其 ctx(阻塞读 1 秒内解除并带回 usage 17);下游新增 TestForwardAsChatCompletions_StreamCancellationIsPerReasoningAttempt 证明 invalid_encrypted_content 拒绝后恰好发起一次同源 reasoning 恢复:两次上游请求 ctx 事后均已取消、第二次保留客户端 deadline 与 HTTPUpstreamProfileOpenAI、URL/Header 相同、第二次 body 等于第一次删去 input.1.encrypted_content、客户端未收到 resp_rejected;客户端取消场景下恢复请求先观察到取消且返回错误不是 UpstreamFailoverError(不重入账号池)。这是对下游 chat_completions.go 逐次尝试 cancelUpstream + recovery.PrepareRequest 机制的正确性证明。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f 为 +110 行:contextBoundChatRecoveryUpstream L121-L155 与新用例 L157-L226;上游原有 TestForwardAsChatCompletions_CancelsUpstreamBeforeClosingBody L81-L119 未变", - "被测代码:openai_gateway_chat_completions.go 恢复循环(attemptCtx/openAIRequestContextReadCloser/recovery.TryRecover/TryRecoverError);fixture reasoningRecoveryFixture、openAIChatReplayTestContext、newOpenAIRejectedFieldTestAccount 定义于其他测试文件", - "未执行测试、未构建;不主张恢复机制在真实上游下的表现。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_chat_completions_raw.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "19900eafecc4e8bd19d8d13352ec8776f6e8cca5d3213125043dee9d16bb4e0d", - "review_fingerprint": "19900eafecc4e8bd19d8d13352ec8776f6e8cca5d3213125043dee9d16bb4e0d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "APIKey/CN/Grok 账号的 Chat Completions 直转路径(无 CC↔Responses 转换)。已按 post-63a98c8cc 冻结版本全文审阅(当前磁盘字节,sha 见本记录)。下游相对上游 aea725f(约 116 行):改用 resolveOpenAIForwardModelContext(Cindy 目录快照映射)与 cindyLegacyLaxaLiveUpstreamModel、新增 applyBusinessSystemPromptForRequest(Chat 协议)+rewriteBusinessSystemPromptCacheKey、service_tier 改在任何变换前提取并直接落 result(配套测试断言 flex 回显)、流式循环接入 decodeCCStreamChunk/semanticOutputReady/protocolErr 并把 [DONE] 早于 finish_reason 判为 upstream_incomplete_response、clientAborted 仅以客户端 ctx 或下游写失败为准(上游 ctx 取消不再伪装成功)、缓冲路径先做 Ollama 清洗与空 tool_call 身份剔除。Grok 分支:customUA 从 defaultGrokUpstreamUserAgent() 改为字面量 'sub2api-grok/1.0',但该值仅在 IsGrokOAuth 时设置且随后被 sendCCUpstreamRequest 中 applyGrokCLIHeaders(openai_gateway_grok.go L1605-L1616) 的 User-Agent Set 覆盖,不上线路;真正的回退是丢失 grokSameAccountRetryMetadata 的同账号重试元数据(见 findings)。静态阅读,未执行。 复审于 12920fa71(HEAD 49c1e8d83):L222 已删除死赋值 customUA=\"sub2api-grok/1.0\"(仅保留 account.GetOpenAIUserAgent()),L250-L259 Grok failover 恢复 grokSameAccountRetryMetadata 并填充 RetryableOnSameAccount/RequestScopedTransient(429)/SameAccountRetryDelay/Deadline/Max,与 openai_gateway_grok.go L191、grok_chat_bridge.go L638 形态一致;新增 openai_gateway_chat_completions_raw_retry_metadata_test.go(3 例:capacity 非 pool 可重试 delay 500ms/max 1、pool 普通限流可重试、pool 免费额度耗尽不重试)静态证明 429 failover 单次上游尝试、不写客户端、Retry-After 与 body 快照、元数据与 RequestScopedTransient 一致。medium finding 已闭合;low(无读间隔上限)为上游继承缺口,仍开放。仅 diff 05e25bdf2..HEAD 两个 hunk,其余字节与前次复审一致;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f 关键锚点:模型策略 L64-L100、业务提示词 L131-L144、Grok UA L222-L225、Grok 错误分支 L235-L261(上游同位置有 grokSameAccountRetryMetadata 与 RequestScopedTransient/SameAccountRetryDelay/Deadline/Max,下游退化为 IsPoolMode&&IsPoolModeRetryableStatus)、streamRawChatCompletions L305-L522(writeLine L335-L368、截断判定 L461-L496)、bufferRawChatCompletions L561-L627", - "对照:下游其余 Grok 路径 openai_gateway_grok.go L191/L1436、openai_gateway_grok_chat_bridge.go L638、grok_media.go L1348 仍使用 grokSameAccountRetryMetadata;grok_upstream_headers.go L22 仍定义 CLI UA", - "观察:streamRawChatCompletions 无读间隔上限、上游 ctx WithoutCancel(TestForwardAsRawChatCompletions_UpstreamRequestIgnoresClientCancel 以此为契约),上游 aea725f 同样如此,系继承缺口(见 findings,低)", - "本记录绑定 post-63a98c8cc 冻结后的当前磁盘字节;未执行测试或构建。", - "复审锚点(12920fa71):diff 05e25bdf2..HEAD 仅 L222 删 3 行、L250-L259 +9 行;新测试 TestForwardAsChatCompletions_GrokRawFailoverPreservesRetryMetadata 使用 Grok APIKey 账号,断言 User-Agent 透传 fixture 值、RetryableOnSameAccount==RequestScopedTransient、SameAccountRetryDeadline 落在 [start+30s, end+30s]" - ] - }, - { - "path": "backend/internal/service/openai_gateway_chat_completions_raw_retry_metadata_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b7e2126d2f22aca4035f42ecfccb661b4cbdabcce360df340919be468c45eccc", - "review_fingerprint": "b7e2126d2f22aca4035f42ecfccb661b4cbdabcce360df340919be468c45eccc", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "一个顶层三种fake429实际经raw Forward:capacity、ordinary pool、free exhausted,断言仅一次发送、未提交输出、客户端UA与响应头快照、重试delay/deadline/max及transient,未测试真实timer/上游。", - "evidence": [ - "artifacts/evidence/v027-astra-grok-raw-retry-review.json", - "Parent full-file fixture review and source SHA verification; targeted execution result reused without rerun" - ] - }, - { - "path": "backend/internal/service/openai_gateway_chat_completions_raw_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "db202551442ce092f3c01f42d8de1db31babc3fdc594e37bc2e235014a3d885c", - "review_fingerprint": "db202551442ce092f3c01f42d8de1db31babc3fdc594e37bc2e235014a3d885c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "raw CC 直转路径的单元测试(1250 行,全文静态读毕):URL 拼接(/v1、/v4、已含端点、空白)、强制 stream_options.include_usage 并向下游透传 usage 与 [DONE]、Grok/x-ai 响应缺 usage 时 502 grok_missing_usage failover 且不写响应、模型映射保留 reasoning_effort=max、非流式缓存写 usage 与 service_tier=flex 回显、DeepSeek reasoning_content 在请求/流式/非流式响应中保留、GLM xhigh→max、静默拒绝 failover 及 tool_calls/reasoning 摘要/正常内容豁免、DashScope 后续 delta 空 tool_call id/name 剔除、已输出后截断或连接重置返回类型化错误而不 failover、空流 failover 事件带托管代理快照、客户端断开/取消仍按已收 usage 收尾、上游请求忽略客户端取消、/responses 未知支持 404 后按版本化 URL 回退、超大响应拒绝。下游相对上游(38 行):fixture 补 finish_reason:'stop'、断言 UpstreamResponseServiceTier=flex、MissingDoneWithUsageStillSucceeds 改为 UsageWithoutFinishDoesNotProveCompletion(有 usage 无 finish_reason 现在报错但仍带回 usage 11/6)、终态表新增「所有 choice 必须终止」且 [DONE]/usage 单独出现均判截断、客户端取消用例改用已取消的请求 ctx。证明下游收紧 CC 流「完成」语义的正确性修复。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f:L93/L377/L511/L1073 fixture 增 finish_reason 或非空 arguments、L312/L327 service_tier 断言、L845-L877 用例改名与 require.Error、L961-L967 已取消 ctx、L999-L1040 openAIRawStreamTerminalState 表格调整", - "被测代码:forwardAsRawChatCompletions/streamRawChatCompletions/bufferRawChatCompletions(本切片 raw.go 冻结版)、openAIRawStreamTerminalState、ensureOpenAIChatStreamUsage、isOpenAIChatUsageOnlyStreamChunk、buildOpenAIChatCompletionsURL/buildOpenAIResponsesURL;helper L1221-L1250", - "未执行测试、未构建;断言语义按源码静态描述。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_cn_fixes_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "71dd9270fd9f90289f2641c2e0d613839302e37b80f939e0e51fb2d7c25553dd", - "review_fingerprint": "71dd9270fd9f90289f2641c2e0d613839302e37b80f939e0e51fb2d7c25553dd", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "国产供应商修复回归测试(260 行,全部为上游 v0.2.7 已有用例):CN 分组(Kimi/Zhipu/DeepSeek/MiniMax/OpenCodeGo)不返回 /v1/messages 调度级默认映射而 openai 分组保留;filterCNProviderBillingModelCandidates 在无显式定价时过滤 claude-* 计费候选(全 claude 清空、非 CN 账号不受影响);calculateOpenAIRecordUsageCost 空候选返回 isUsagePricingUnavailableError(零成本落账而非丢弃用量行);Responses×anthropic 流式转换器客户端断开后继续排水(output_tokens=5 来自末尾 message_delta);CN 403 处置(HTML 403 不惩罚账号、结构化 403 首次临时停调 1/3、Kimi 并发限流精确匹配走临时冷却+运行时 block 且仓库失败不降级为永久错误、近似措辞与其他 CN 平台保持普通策略)。下游相对上游仅 L73 调用点适配:calculateOpenAIRecordUsageCost 新增第 5 个参数 billingModels []string(计费候选链,openai_gateway_usage.go L584-L599),测试传 nil。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f 仅 2 行(L73-L74 调用签名适配);所有断言与上游一致", - "被测对象:Group.ResolveMessagesDispatchModel、OpenAIGatewayService.filterCNProviderBillingModelCandidates / calculateOpenAIRecordUsageCost(openai_gateway_usage.go L584)、RateLimitService.HandleUpstreamError、isCNProviderConcurrencyLimit403、handleResponsesStreamingFromNativeAnthropic", - "未执行测试、未构建;仅静态描述断言语义。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_count_tokens.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "bffdb654fa5f9e819e84584000ae0c9082456cb386a50f1fa0235f32984a475b", - "review_fingerprint": "bffdb654fa5f9e819e84584000ae0c9082456cb386a50f1fa0235f32984a475b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "token 预估端点:/v1/responses/input_tokens 原生转发(自定义 relay/Grok/CN/Upstream 账号本地 tiktoken 估算)与 Anthropic /v1/messages/count_tokens→input_tokens 桥接(CN/OpenCode 一律本地估算;OAuth 缺 scope/HTML 403/404 回退本地估算且不触发账号处置)。下游相对上游(约 47 行):两个入口前置 EnsureCindyProviderAvailable(cindy_pricing_snapshot.go L130→cindyProviderAdmissionOwner→invokeProcessExtensionCached('cindy.features'),插件不可用即 503,防止无策略时把请求发给 Cindy 上游);桥接路径传输层错误改走 handleOpenAIUpstreamTransportError(归一为 failover 而非终态 502);>=400 新增 shouldFailoverOpenAIUpstreamResponseForAccount 分支:执行账号处置、pool 重试标记,Cindy runtime 账号命中 isOpenAIModelNotSupportedError 时返回 newOpenAIModelNotSupportedFailoverError;上游 200 缺 input_tokens 从终态 502 改为 NextAccountRetry 的 UpstreamFailoverError。模型映射仍用 resolveOpenAIForwardModel——其 account.ResolveMappedModel(account.go L968-L985) 对 Cindy 账号经 CindyCompatibilityMappedUpstreamModel 等 queryCindyCatalog 插件调用解析别名,宿主无别名表,无二次执行体。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff 锚点:L53-L56 与 L266-L269 EnsureCindyProviderAvailable、L334-L343 transport 错误归一、L352-L372 failover 分支与 Cindy model_not_supported、L401-L412 缺 input_tokens 改 failover", - "调用链:prepareOpenAIInputTokensCountRequest/prepareNativeOpenAIInputTokensCountRequest→resolveOpenAIForwardModel→account.ResolveMappedModel→CindyCompatibilityMappedUpstreamModel(cindy_capability_catalog.go L121, queryCindyCatalog→invokeProcessExtensionCached 'cindy.catalog');估算器 estimateOpenAIInputTokens L596-L804(tiktoken o200k/cl100k 按模型族选择)", - "本地估算不发上游请求;未执行测试或构建,未对照真实 OpenAI 端点。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_count_tokens_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1c13cfe771e5e522b4e4bec8d032d3fa8fa6c59b85fdfe7ac6e8a8057addc2cb", - "review_fingerprint": "1c13cfe771e5e522b4e4bec8d032d3fa8fa6c59b85fdfe7ac6e8a8057addc2cb", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "count_tokens 桥接与本地估算的单元测试(439 行):APIKey 账号桥接到 {base_url}/v1/responses/input_tokens 且 Anthropic body 转成 input/instructions 形态、Bearer 头正确;OAuth 在 401/403 missing_scope、HTML 403 代理页、404 端点缺失时回退本地 tiktoken 估算并断言不 temp-unschedule/不 SetError;估算失败用最小值 1;estimateOpenAIInputTokens 样例值(6/50/24)与编码选择(gpt-3.5/gpt-4-turbo→cl100k,其余→o200k);EstimateGrokCountTokens 正例与拒绝无 model/畸形 body;可选 OPENAI_API_KEY 真实 API 对照(无 key 即 skip,误差 ≤max(24, actual/4))。下游相对上游新增 TestLegacyCindyRuntimeCompatibilityCountTokensMapsPublicAliases(L90-L112):legacy Cindy 账号(base_url=api.laxarouter.ai)请求别名 gpt-5.4-mini 时 prepare 结果的 Billing/Upstream/Request.Model 均为 openai/gpt-5.6-luna,证明别名经 account.ResolveMappedModel→插件目录(CindyCompatibilityMappedUpstreamModel)解析而非宿主表。静态阅读,未执行(含可选网络用例在本审阅中未运行)。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f:+24 行即新增 legacy Cindy 别名映射用例;其余用例与上游一致", - "被测对象:ForwardCountTokensAsAnthropic、prepareOpenAIInputTokensCountRequest、writeOpenAIOAuthInputTokensFallback、estimateOpenAIInputTokens、openAIInputTokensEncodingForModel、EstimateGrokCountTokens(本切片 count_tokens.go)", - "未执行测试;不主张估算值与 OpenAI 真实计数的当前偏差。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_deepseek_chat_reasoning_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b21cdb8e4549b0aff435ea225a65eb111aa40e7b48bb1d9c1890bdaff18e620c", - "review_fingerprint": "b21cdb8e4549b0aff435ea225a65eb111aa40e7b48bb1d9c1890bdaff18e620c", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_gateway_forward.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "53c8f2605a897f58bb616fb1f28dbbf370123c633c65a42bb0b2571cfea1c488", - "review_fingerprint": "53c8f2605a897f58bb616fb1f28dbbf370123c633c65a42bb0b2571cfea1c488", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "/v1/responses 主转发(已按 post-63a98c8cc 冻结版本全文审阅,当前磁盘字节 1825 行)。下游相对上游 aea725f(约 781 行)为宿主机制扩展+插件委托,无域规则重实现:入口 Cindy 图像桥(bindProcessExtensionContext 'image.responses.plan'→ResolveCindyResponsesImageToolsForAccount,失败按 404 model_not_found/503 区分;后续 mapCindyOpenAIResponsesImageModels、ResolveCindyCapability 均为扩展调用);CaptureCindyPricingContext;请求完整性 stage/check(stageRequestIntegrityOriginal→checkStagedRequestIntegrity 在最终 wire body 上重放服务侧改写);Cindy 免费池端点校验与目录快照模型映射(LoadCindyCatalogSnapshot);Cindy HTTP→WSv2 严格桥(bypass 上下文、首轮 failover、handshake_forbidden 时无状态 HTTP 回退、failover 只允许桥兼容账号);previous_response_id 在非 WSv2 的 Codex 协议下直接 400(上游原为删字段继续);WS 重试环去掉上游的 previous_response_not_found/invalid_encrypted_content 剥离重放,改为终止并返回 ContinuationStateUnavailable(注释:被拒不证明加密项可弃,重建属 WS ingress 生命周期);HTTP 环引入 reasoning 恢复状态机(PrepareRequest/TryRecover/TryRecoverError/MarkAttemptDispatched)、continuation-state 与 request-rejected 分类+诊断、compact 回退重试、openAIHTTPPoolRetryable、Cindy 403 failover 脱敏;buildUpstreamRequest:SetupToken 恒 chatgptCodexURL、applyOpenAICodexTicket(codex_ticket_plugin.go→pluginManager.ApplyRequestHeaders,codex-runtime 插件)、enforceCodexIdentityHeadersForAccountContext 终态收口、指纹收敛 staged IDs 与 sandbox↔UA 对齐、ensureCodexSessionIdentityHeaders;业务系统提示词为最终层+Cindy 管理缓存键归一;opaque continuation 账号绑定;doOpenAICodexUpstream(zstd)。删除影子账号 notifyOpenAIAutoReset。静态阅读,未执行。 复审于 6258adab5(HEAD 49c1e8d83):仅 L1128-L1132 新增——Cindy HTTP→WSv2 桥成功返回前调用 s.bindHTTPResponseAccount(ctx, c, account, wsResult.ResponseID),受 cindyHTTPToWSV2 守卫(仅 HTTP 入站);该 helper(openai_gateway_response_handling.go L1643-L1687)即 HTTP 环 L1517 与 passthrough L682 已用的同一绑定:以 WithoutCancel+超时的有界 ctx 把 response_id→account 写入 WS 状态存储(sticky TTL),并在 handler 已 stage openAIHTTPResponseOwnerContextKey 时复用该所有者绑定 BindOpenAIHTTPResponseOwner;不触及计费、WS 重试预算或原生 WS 入口(原生 WS 不经 Forward())。同 commit 另改 handler/openai_gateway_handler.go 与新增 owner 测试,不在本切片。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "frozen 版本全文读毕:L22-L48 图像桥+定价捕获、L57-L84 模型策略与完整性 effort 重放、L165-L199 Cindy HTTP→WSv2 与 previous_response_id 门、L459-L621 图像工具/映射/Codex spark 校验、L623-L689 Codex 变换与指纹、L757-L790 fast policy、L863-L901 业务提示词+缓存键、L933-L1155 WS 环(budget/backoff/ctx.Done、strictCindyContinuation、handshake 回退)、L1157-L1560 HTTP 恢复环、L1587-L1739 buildUpstreamRequest、L1744-L1825 UA 预测与 WS 帧指纹", - "取消与清理:HTTP 上游 ctx 经 detachUpstreamContext(WithoutCancel+插件策略信号)故客户端断开不取消上游(排水计费契约),首输出由 openAIFirstOutputHeaderGuard 限时,WS backoff 显式监听 ctx.Done();错误体读取后 Close 并以 NopCloser 回卷;重试 continue 前均显式 Close resp.Body", - "上游被移除的 minimal→none effort 改写与 JSON-schema 归一化由 normalizeOpenAIResponsesReasoningModeForModel(按最终模型)与下游其他归一层接替;normalizeOpenAIAPIKeyStoreFalseReasoningReplay 移除,replay 逻辑并入 reasoning 恢复态;未逐一验证所有被移除路径的等价替代,此处只记录 delta 事实", - "本记录绑定 post-63a98c8cc 冻结后的当前磁盘 sha256;未执行测试、构建或网络。", - "复审锚点(6258adab5):diff 05e25bdf2..HEAD 仅 +5 行 L1128-L1132;bindHTTPResponseAccount 调用点 forward.go L1131/L1517、passthrough.go L682;所有者由 openai_v183_compat.go L320 在 handler 侧 stage" - ] - }, - { - "path": "backend/internal/service/openai_gateway_grok.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "74e2185589dfbf28fd938db7f6b0668b97b1fd77c5a2bb1bb295d79f6cf711a7", - "review_fingerprint": "74e2185589dfbf28fd938db7f6b0668b97b1fd77c5a2bb1bb295d79f6cf711a7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Grok 平台 /v1/responses 转发与账号健康处置(2117 行全文读毕):模型别名规范化、compact 转普通 turn、prompt-cache 身份、invalid_encrypted_content/compaction 解码错误的单次同账号重放剥离、体清洗链(reasoning effort 归一、null 剥离、additional_tools 提升、view_image 冗余剥离、工具类型白名单与 union-root 参数兜底)、Composer 图片描述桥(grok-build-0.1 辅助请求计费并入 bridgeUsage)、配额快照解析与调度阈值 extras、自适应重复限流冷却、团队+模型级冷却、403/402/5xx 处置策略。下游相对上游 aea725f 仅 2 行:rateLimitGrok 与 tempUnscheduleGrok 的运行时封锁从 BlockAccountScheduling 改为 BlockAccountSchedulingFromPersistedCooldown(openai_account_runtime_block_fastpath.go L752-L761:仅镜像普通 DB 冷却字段,Cindy runtime 账号仍走原函数),使持久化冷却与请求内封锁语义分离。Grok 为宿主网关协议(非七插件域),归 core。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f:L1881 与 L2111 两处调用改名;其余 2115 行与上游一致(含 grokSameAccountRetryMetadata 的三处使用 L191/L1436/L638-bridge)", - "关键锚点:forwardGrokResponses L34-L275(重放剥离环 L112-L158)、sanitizeGrokResponsesTools L1073-L1170、bridgeGrokComposerImageInputs L1263-L1303(辅助请求经 buildGrokResponsesRequest 不绑定会话缓存身份 L1393-L1396)、updateGrokUsageSnapshotWithRateLimit L1622-L1675(快照节流、pool 模式跳过限流安装)、grokRateLimitResetAtForAccount L1780-L1809(自适应 10m/30m/1h 冷却)、handleGrokAccountUpstreamError L2009-L2080", - "未执行测试或构建;不主张 xAI 上游当前真实行为。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_grok_405_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6fcbec5bb6047cec8de6498d4478aff99d10ff8d01f7963300c11c6c0e6cb98f", - "review_fingerprint": "6fcbec5bb6047cec8de6498d4478aff99d10ff8d01f7963300c11c6c0e6cb98f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "shouldFailoverUpstreamError 的状态码表测试(29 行)。下游相对上游把 408 从非 failover 列表移入 failover 列表:断言 401/402/403/405/408/429/529/5xx 触发换号而 200/201/400/404/422 不触发,即下游把上游请求超时 408 视为可换号错误的正确性修复的测试面。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f:L20 failoverCodes 增 408、L25 nonFailoverCodes 移除 408(共 4 行)", - "被测函数 shouldFailoverUpstreamError 位于 openai_gateway_upstream_errors.go(另一切片),此处只主张测试断言语义", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_grok_chat_bridge.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "28904c774f2cc8f67b730915b897bf54604db32d7ca2246d82b34a7a215655d6", - "review_fingerprint": "28904c774f2cc8f67b730915b897bf54604db32d7ca2246d82b34a7a215655d6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Grok OAuth 的 Chat Completions→Responses 桥(670 行全文读毕):grokChatResponsesBridgeEligibility 以白名单顶层字段+逐字段结构校验保证只有语义可无损转换的请求走桥(未知字段/角色/工具形态一律回落 raw CC);forwardGrokChatCompletionsViaResponses 复用 CC→Responses 转换、桥模型限 grok-4.5/4.6、图像输入强制走桥、缓存意图体与缓存身份、fast policy、共享 handleChat{Streaming,Buffered}StreamingResponse 回程转换;错误路径保留完整 grokSameAccountRetryMetadata 元数据(与 raw.go 的退化形成对照,见该文件 finding)。下游相对上游仅 L617 readOpenAIUpstreamError(resp, c) 签名适配,无行为差异。宿主协议机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f:仅 L617 一处调用签名变化", - "锚点:eligibility L49-L250(消息角色/工具/流选项逐项校验)、桥模型门 L499-L510、forwardGrokChatCompletionsViaResponses L516-L670(cache intent L563-L569、failover 元数据 L637-L648)", - "未执行测试或构建。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_grok_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7cf39c97ce6b0b393669ac17af737655e3f3d6644b00a05ed28d6b5ef292c761", - "review_fingerprint": "7cf39c97ce6b0b393669ac17af737655e3f3d6644b00a05ed28d6b5ef292c761", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Grok 网关的大型单元测试套件(3803 行,全文静态读毕),主体为上游 v0.2.7 既有用例:patchGrokResponsesBody 体清洗矩阵(模型映射、unsupported 字段、composer reasoning 剥离、effort 别名归一、logprobs/4.20、view_image 冗余剥离、namespace 展平、additional_tools 提升与去重、null 剥离但 compaction 项不动、union-root 参数兜底)、compact 转换往返、缓存身份与 Free 工具缓存路由(Codex/Claude Desktop 两类客户端、failover 跨账号保持同一 identity)、媒体端点(images/videos 生成/编辑/状态,multipart→JSON、别名归一、模型映射、几何字段、绑定按 user+apiKey 作用域)、invalid_encrypted_content/compaction 一次性重放剥离及不过度匹配、配额快照/自适应 429 冷却/恢复清除/pool 模式豁免/调度阈值 extras 驱动 EvaluateAccountSchedulingThreshold、WS HTTP 桥 429 持久化限流。下游相对上游仅 4 处(约 12 行):两处流式 fixture 补 finish_reason:'stop'(跟随 raw CC 终止语义收紧,否则新判定会把旧 fixture 当截断);TestOpenAIWSHTTPBridgeSSEErrorSideEffectsRunOncePerPlatform 改为 PlatformOpenAI 的 429 SSE error 不直接调 repo 限流(仅 Grok 平台记 1 次,OpenAI 走 rateLimitService 策略);failoverOpenAIUpstreamHTTPError 调用去掉 upstreamMsg 参数。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "diff vs aea725f:L2567/L2740 fixture 增 finish_reason、L3596-L3600 平台分叉断言、L3645 签名适配", - "被测对象覆盖本切片 openai_gateway_grok.go 与 grok_chat_bridge.go 的几乎全部导出/内部函数,另涉 grok_media.go、openai_gateway_ws_*(其他切片);helper healthyGrokOAuthGatewayTestAccount/grokMessagesSSECompletedResponse 定义于本文件 L1909/L3002", - "未执行测试、未构建;断言语义按源码静态描述,不主张 xAI 上游现行为。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_merge_contract_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "73bf26e44d233656a0ebfc7c53fdd016ea6b927821faffd5d2362167cb8e0553", - "review_fingerprint": "73bf26e44d233656a0ebfc7c53fdd016ea6b927821faffd5d2362167cb8e0553", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增文件(上游无此文件):v0.2.7 合并后错误分类契约的守护测试(121 行)。证明:(1) 流式请求命中 missing-model 400 时返回可换号的 UpstreamFailoverError 且不落入通用流式 400 终态(c.Writer 未写、非 RequestRejected);(2) 请求作用域失败码(cyber_policy / previous_response_not_found / invalid_encrypted_content / context_length_exceeded)即使 message 含 'model not found' 也绝不 failover(shouldFailoverOpenAIUpstreamResponse 与 ForAccount 变体均为 false);(3) 安全终态跳过一切账号副作用:对 OAuth/APIKey × 401/403/502,handleOpenAIAccountUpstreamError、流终态副作用与非流终态 failover 均不触发 SetError/temp/运行时封锁;(4) 安全判定只认结构化 error.code,不扫描回显文本(echo 中的 cyber_policy 或 message 提及不算命中);(5) passthrough 安全终态把 usage(17/3) 写入 CyberPolicyMark 供计费读取,错误非 failover 且客户端收到 cyber_policy 而无 response.completed。这是对下游合并期间错误优先级契约的正确性证明。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "git ls-tree aea725f 无此路径(全文件即下游 delta);fixture/stub(newOpenAIRejectedFieldTest*、modelNotFoundManagedAccountRepo、openAIAuthPolicyAccountRepo、newOpenAIRefusalRecoveryPipelineService)定义于其他测试文件", - "被测函数:Forward、shouldFailoverOpenAIUpstreamResponse(ForAccount)、isOpenAIRequestScopedSafetyRejection、shouldFailoverOpenAIPassthroughResponse、handleOpenAIAccountUpstreamError、handleOpenAIStreamTerminalAccountSideEffectsWithContext、nonStreamingTerminalFailureFailover、handleStreamingResponsePassthrough、GetOpsCyberPolicy", - "未执行测试、未构建。" - ] - }, - { - "path": "backend/internal/service/openai_gateway_messages.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e29ae30b7928244d89a4d8c9f7f71c84e45694eef2d396d31159cae8badbdf0a", - "review_fingerprint": "e29ae30b7928244d89a4d8c9f7f71c84e45694eef2d396d31159cae8badbdf0a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Anthropic /v1/messages→OpenAI Responses 兼容桥(已按 post-63a98c8cc 冻结版本全文审阅,1447 行):协议分流(OpenCodeGo/anthropic/adaptive/raw-CC)、Anthropic→Responses 转换、compat prompt_cache_key 派生(Claude Code 会话/metadata/cache_control/摘要链)、previous_response_id 续链存取与降级重试、Codex OAuth 变换与身份恢复、Grok 缓存身份与一次性 encrypted_content 剥离重试、流式/缓冲 Anthropic 回程转换。下游相对上游 aea725f(约 227 行):入口 CaptureCindyPricingContext 与 resolveOpenAIForwardModelContext(插件目录/模型策略);新增 compatSessionSeed 把本地续链/摘要/turn-state 键与 wire 上的 prompt_cache_key 解耦(业务提示词改写 key 后本地状态仍按原 seed 存取,递归重试也传 seed);applyBusinessSystemPromptForRequest+rewriteBusinessSystemPromptCacheKey+normalizeCindyManagedPromptCacheKey 得到 upstreamPromptCacheKey;fillCodexSessionIdentityHeaders 与 enforceCodexIdentityHeadersForAccountContext(账号级 Codex TUI 身份);applyOpenAICodexTicket(codex-runtime 插件经 pluginManager.ApplyRequestHeaders);doOpenAICodexUpstream(zstd);readOpenAICompatBufferedTerminal 改为返回 terminalPayload、新增 openAICompatBareErrorResponse(bare error 事件合成 failed 响应)与 deferSignatureRejection(chat 路径延迟签名拒绝以便恢复态接管),终态事件集合收窄为 completed/done/incomplete/failed;ServiceTier 从上游回显优先改为最终出站 body 归一值(回显 tier 仍经 UpstreamResponseServiceTier 供计费仲裁);删除 codexResult.Error 分支、restoreCodexToolNamesFromContext(由 observe*+业务提示词回写取代)、logOpenAISuccessMissingUsage 与影子账号 notifyOpenAIAutoReset(并入既有 finding,低)。宿主协议机制,域规则均经插件或既有 Codex 助手。静态阅读,未执行。 复审于 5ce1d85fe(HEAD 49c1e8d83):恢复观测钩子——L586-L587 影子账号成功后 notifyOpenAIAutoReset(*account.ParentAccountID)(与上游同位置,handleErr==nil 时一次);L731-L733 缓冲成功(status completed)与 L1233 流式 finalizeStream(新增 terminalEventType 跟踪)各调用一次 logOpenAISuccessMissingUsage(纯日志采样告警,无计费/状态变更)。两分支互斥,无重复通知。同 commit 新增 openai_compat_host_observation_test.go 覆盖 messages 协议的缺 usage 单次告警、影子单次通知、失败/incomplete 不发信号。仅 diff 05e25bdf2..HEAD 四个 hunk(+8 行),其余字节与前次复审一致;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S09-svc-openai-gateway-1-review.json", - "frozen 版本全文读毕:ForwardAsAnthropic L28-L590(compat 缓存键派生 L98-L149、续链 L136-L177、Codex 变换 L216-L268、业务提示词+Cindy 缓存键 L321-L349、Grok 体处理 L350-L366、发送与 Grok 剥离重试环 L440-L487、错误/降级 L491-L531)、handleAnthropicBufferedStreamingResponse L622-L730、readOpenAICompatBufferedTerminal L778-L955(interval timer L793-L828、bare error 与签名延迟 L855-L944)、handleAnthropicStreamingResponse L982-L1403(interval/keepalive 双 ticker)", - "diff -U0 vs aea725f 核对全部 hunk;compatSessionSeed 改动覆盖 getOpenAICompatSessionResponseID/TurnState、disable/delete continuation、bind* 共 10 处调用点与 3 处递归重试传参", - "本记录绑定 post-63a98c8cc 冻结后的当前磁盘 sha256;未执行测试、构建或网络。", - "复审锚点(5ce1d85fe):diff 05e25bdf2..HEAD +8 行(L586-L587、L731-L733、L1003、L1097、L1233)" - ] - }, - { - "path": "backend/internal/service/openai_gateway_messages_anthropic_native.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "4edfef4987439f9ed26d26bfe83bb5be3e5eeafb621ab4ba2be76766e5988d4c", - "review_fingerprint": "4edfef4987439f9ed26d26bfe83bb5be3e5eeafb621ab4ba2be76766e5988d4c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "国产供应商(kimi/zhipu/deepseek)原生 Anthropic /v1/messages 零转换直通:模型映射、beta 能力字段清洗、字节级 SSE 中继+keepalive、断连后继续拉流保 usage、claudeUsageToOpenAIUsage 把缓存 token 合入 InputTokens 供 RecordUsage 拆桶。下游相对 aea725f 仅改错误读取签名(readOpenAIUpstreamError 增 gin 上下文参数、failoverOpenAIUpstreamHTTPError 去掉 upstreamMsg 参数),是宿主协议机制的重构,无插件域业务规则。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: only L107-L115 error-read refactor (readOpenAIUpstreamError(resp,c), failoverOpenAIUpstreamHTTPError drops upstreamMsg); rest byte-identical to upstream blob 263eceba0", - "Anchors: forwardAnthropicViaNativeAnthropicEndpoint L36-L124, handleNativeAnthropicStreamingResponse SSE relay with keepalive/interval timers L288-L530, claudeUsageToOpenAIUsage cache-token merge L552-L571; scanner buffer bounded by cfg MaxLineSize, pooled via getSSEScannerBuf64K", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_messages_chat_fallback.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "93c6fa435a938f381c8080df6f310801e92dd73edf56a0a32a84eae7429e9c43", - "review_fingerprint": "93c6fa435a938f381c8080df6f310801e92dd73edf56a0a32a84eae7429e9c43", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "/v1/messages 客户端经仅支持 chat/completions 的上游转发:Anthropic→CC 请求转换与 CC→Anthropic 单状态机流式桥接。下游新增 (1) resolveOpenAIForwardModelContext——对 Cindy 兼容账号经 LoadCindyCatalogSnapshot(invokeProcessExtensionCached 调 cindy-provider 扩展的 cindy.catalog)取快照做模型解析(冻结提交 63a98c8cc 引入的请求级快照绑定);(2) applyBusinessSystemPromptForRequest+rewriteBusinessSystemPromptCacheKey——提示词计划经 invokeProcessExtension 委派扩展;(3) 错误读取签名重构;(4) scanCCStream 增 account 参数。域规则均经扩展宿主委派,文件本体是协议机制。审阅对象为协调者宣布冻结后的在盘字节(sha 93c6fa43…)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Post-freeze bytes reviewed (295 lines, sha256 93c6fa435a93...), delta vs aea725f: model resolution via resolveOpenAIForwardModelContext (openai_model_mapping.go L29 -> LoadCindyCatalogSnapshot -> cindy_catalog_snapshot.go L71 invokeProcessExtensionCached cindy.catalog), business system prompt block L102-L115, error-read refactor L142-L143, scanCCStream account param L236", - "Stream bridge: emitChunk keeps feeding anthropicState after client disconnect so finalize usage stays complete (L210-L234); scan.Err path skips finalization and flags usage incomplete (L239-L258)", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_messages_chat_fallback_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b5cc103fa06f47b075da0110556ade7513294e7f77aefbf3f19e637a249f6ada", - "review_fingerprint": "b5cc103fa06f47b075da0110556ade7513294e7f77aefbf3f19e637a249f6ada", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "ForwardAsAnthropic 强制 CC 回退路径的单测:断言 reasoning_effort 映射与策略封顶(gpt-5.6 max/gpt-5.5 xhigh/策略 cap medium)、非流式 CC→Anthropic 转换与缓存 token 记账、流式状态机 content_block_stop→message_delta→message_stop 顺序、tool_call 分片聚合、length→max_tokens、非 failover 4xx 走共享错误处理器并记录 ops 事件、流中断不合成 message_stop、Responses 可用账号仍走 /v1/responses。下游 delta 把空流测试改写为 EmptyStreamRequiresTerminal:仅 [DONE] 或 EOF 无语义 finish_reason 必须报错——证明下游终止事件强制的正确性修复。测试对象是核心协议转换,非插件行为。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: TestForwardAsAnthropic_ForceChatCompletionsEmptyStreamRequiresTerminal (L322-L365) replaces EmptyStreamStillFramesMessage - sentinel_only/eof_only now require.Error and assert no message_stop", - "Other proven behaviors: shared error handler ops recording (OpsUpstreamStatusCodeKey/OpsUpstreamErrorsKey asserts L398-L416), stream read error skips finalize (L419-L457), responses-capable gate keeps /v1/responses with header passthrough asserts (L460-L499)", - "Statically read only; assertions were not executed." - ] - }, - { - "path": "backend/internal/service/openai_gateway_model_availability.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0abae6488af4a8213545492ddaf6040d7aaff8038f120146bb4346abf339e045", - "review_fingerprint": "0abae6488af4a8213545492ddaf6040d7aaff8038f120146bb4346abf339e045", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "503 错误路径上的模型可用性诊断:查组内持久可调度账号是否配置了请求模型,任何内部失败都回退 {true,true} 保持 503。下游相对上游不再首个命中即返回,而是统计所有支持账号,并当全部为 Cindy 兼容账号且都处于 model_not_supported 限流冷却时置 ModelNotSupportedCooldownExhausted,供上层区分暂时冷却与真不支持。Cindy 判定仅为账号身份谓词+读既有冷却原因,属调度诊断机制而非域规则再实现。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f L56-L75: supportingAccounts/modelNotSupportedCooldowns counters; ModelNotSupportedCooldownExhausted = supportingAccounts>0 and all cooling; per-account gate IsCindyRuntimeCompatibleAPIKeyAccount + hasActiveModelRateLimitReasonWithContext(openAIModelNotSupportedReason)", - "Conservative fallbacks unchanged: nil service/empty model/repo error all return {true,true} so callers stay on 503 (L26-L54)", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_ollama_cloud_cc_reasoning_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bf6d94f611a5a91e6764ced90a3c1fe9d2693e03b2ec38433164c735971e0f1a", - "review_fingerprint": "bf6d94f611a5a91e6764ced90a3c1fe9d2693e03b2ec38433164c735971e0f1a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Ollama Cloud CC 路径 reasoning/thinking 别名归一的单测:账号识别谓词(ollama.com+force_chat_completions、用量快照信号、官方 DeepSeek/OpenCode Go 反例)、请求侧 reasoning_content→reasoning 补写、响应/SSE 侧 reasoning/thinking→reasoning_content 补写且不覆盖已有值、外域账号不改写、流式与非流式端到端断言。下游 delta 仅 1 行:流式 fixture 的最后内容块补 finish_reason=stop,使其在下游【空流需语义终止事件】规则下仍然有效——属对该正确性修复的测试适配。上游宿主协议怪癖归一属核心机制,无插件域规则。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: single fixture line L209 adds finish_reason stop (was null) in TestForwardAsRawChatCompletions_OllamaCloudReasoningAliasStreaming - required by the downstream semantic-terminal rule proven in messages_chat_fallback_test", - "Proven behaviors: isOllamaCloudRawChatCompletionsAccount matrix L36-L90, normalize request/response/SSE alias copies without overwrite L92-L193, streaming/non-streaming forwards preserve aliases and reasoning_tokens L195-L269", - "Statically read only; assertions were not executed." - ] - }, - { - "path": "backend/internal/service/openai_gateway_passthrough.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9472b1b4b59ae68d9959106b93d2b657f64a6bb5eac49d545cc8930af8441088", - "review_fingerprint": "9472b1b4b59ae68d9959106b93d2b657f64a6bb5eac49d545cc8930af8441088", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "/v1/responses 透传主管线(3083 行,审阅冻结后字节 sha 9472b1b4…,含冻结提交 63a98c8cc 的快照绑定改动):出站请求构造、SSE 字节级中继、pre-output failover 与 pendingLines 缓冲、流内 error/response.failed 语义分类、非流式 SSE→JSON。下游相对 aea725f 增加的都是经扩展宿主委派或账号级机制:legacy Laxa store=false 归一与 cindyLegacyLaxaLiveUpstreamModel(目录快照来自 cindy-provider 扩展)、业务系统提示词应用(经 invokeProcessExtension)与 Cindy prompt_cache_key 归一、Codex 指纹/票据(applyOpenAICodexTicket→pluginManager.ApplyRequestHeaders)/turn-state 溯源/身份终态收口、推理恢复状态机、请求完整性校验、Cindy 余额终止事件 failover 与 opaque 续写绑定(bindCindyOpaqueContinuationAccount)、拒答改写流、容量降载错误码改写、空 completed 视为静默拒绝切号(#5009)。usage 与 responseID 均绑定实际服务账号;defer 关闭 body/停 keepalive/归还扫描缓冲,断连后继续拉流保 usage;scanner 以 MaxLineSize 限界。域逻辑未见在此重实现(票据/目录/提示词均为委派调用)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Post-freeze bytes (3083 lines) read to EOF; delta vs aea725f ~1296 lines: Laxa normalize+catalog model L139-L195, business prompt+normalizeCindyManagedPromptCacheKey L331-L366, reasoningRecovery state machine L448-L470 plus retry loop, checkStagedRequestIntegrity L481-L484, handleCindyBalanceHTTPFailover L523-L527, agent task recovery L562-L570, opaque binding IDs L604+L683 bindCindyOpaqueContinuationAccount, codex ticket L817 applyOpenAICodexTicket -> codex_ticket_plugin.go L56 pluginManager.ApplyRequestHeaders, fingerprint staging L256+L901, turn-state staging/commit L2148-L2186, refusal stream L2211-L2230, capacity shed code sanitize L1560-L1600, empty completed failover around L2600", - "Ownership tracing: cindyLegacyLaxaLiveUpstreamModel -> cindy_catalog_snapshot.go L252 cindyLegacyLiveModel reads plugin-served snapshot (invokeProcessExtensionCached cindy.catalog L71); prompt planning via planBusinessSystemPromptWithInvoker(invokeProcessExtension); no second executor found in this file", - "Resource/identity checks: defer resp.Body.Close/stopKeepalive/putSSEScannerBuf64K/flushPendingOutput; client disconnect keeps draining for usage; pendingLines pre-output buffer exists in upstream aea725f too (upstream L1880-L1932), not a downstream regression; usage-to-account binding via bindHTTPResponseAccount plus opaque IDs", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_passthrough_flush_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "41b5397f5d4671010333590727832c3285c32d8611f3b096dc0e4b7df1a779d3", - "review_fingerprint": "41b5397f5d4671010333590727832c3285c32d8611f3b096dc0e4b7df1a779d3", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "透传流式 flush/commit 边界单测:按 SSE 事件边界 flush、preamble 挂起到首个输出、EOF 无空行也冲刷终止事件、pre-output failed 可无写出 failover、content_policy 不可重试原样透传、裸 error 由 ensureResponseFailedTerminal 合成 response.failed 且吞掉 [DONE]、断连/空行写失败后仍拉完终止 usage、namespace 还原错误只冲刷已写残留。下游 delta 新增 SignatureFailureRespectsCommitBoundary:invalid_encrypted_content 在语义输出前必须变为 continuation-state failover(不换号重试、不计调度失败、不向客户端泄露错误码),语义输出后则如实在流内上报——证明下游 continuation-state 提交边界修复。核心流式机制,静态阅读未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: TestOpenAIStreamingPassthroughSignatureFailureRespectsCommitBoundary L254-L295 (+43 lines) asserting IsOpenAIContinuationStateUnavailable, ShouldRetryNextAccount()==false, body free of invalid_encrypted_content pre-output; post-output real failure passthrough", - "Existing proven behaviors: flushBodyLengths boundary accounting L107-L161, bare-error synthesis NotContains type:error plus one response.failed L194-L234, disconnect drain keeps usage 11/4 L297-L314", - "Statically read only; assertions were not executed." - ] - }, - { - "path": "backend/internal/service/openai_gateway_record_usage_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "30e8e644039894ee9520fa511eb468bf14d644631c22ebcbe1a43ca8b98d5713", - "review_fingerprint": "30e8e644039894ee9520fa511eb468bf14d644631c22ebcbe1a43ca8b98d5713", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "RecordUsage 计费/记账单测(3297 行全文静态阅读)。上游 aea725f 已含绝大部分内容:cyber 按真实 token 计费、零用量仍落 usage_log、缺价零费、用户组倍率/峰时/时段定价(PricingAt)、DeepSeek 账户统计用上游模型+历史时点、请求 ID 优先级(client>upstream、WS 反转、generated 兜底)、计费与请求上下文解耦(detached ctx)、usage_log 写失败不跳过扣费、billing key 幂等、长上下文阶梯(组/账号开关、Grok 仅组开关、Spark shadow 用父账号当前设置)、service_tier 定价(priority/flex/降级不升级/Codex default 回显仍按 fast/FreeOpenAIFast 组按标准价)、channel 映射计费模型来源规则、图像/视频分辨率分档与独立倍率、token 渠道计费保 video 元数据(迁移 172 约束)。下游 delta 仅 +42 行:新增 UsageCommitObserver 断言——billing Applied 才回调、恰好一次且携带真实服务账号 ID(30046),重复 usage_log/重复 billing key 不回调——证明下游 usage 提交观察者(经 wire.go DI 注入)的幂等与账号绑定语义。核心配额计费机制,非插件行为。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f (+42): SetUsageCommitObserver asserts in DuplicateUsageLogSkipsBilling L753-L780 (observerCalls==0), DuplicateBillingKeySkipsBillingWithRepo L783-L817 (==0), new TestOpenAIGatewayServiceRecordUsage_AppliedUsageNotifiesCommitObserverOnce L819-L852 (once, observedAccountID==30046); observer defined gateway_service.go L873 / openai_gateway_service.go L560, fired in gateway_usage_billing.go L894 only when applied && logPersisted, wired in wire.go L350-L351", - "Account/identity binding proven: DeepSeek AccountStatsCost uses UpstreamModel + request PricingAt (L573-L640), shadow parent contract fetches parent account for tier/long-context settings (L1465-L1508, L3160-L3202); detached-context billing survives cancelled request ctx (L905-L975)", - "Statically read only; assertions were not executed." - ] - }, - { - "path": "backend/internal/service/openai_gateway_request_body.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f8d86068a8e75de4683f1735a81de79c934a199adaf81b9b43a08992f61fa1a5", - "review_fingerprint": "f8d86068a8e75de4683f1735a81de79c934a199adaf81b9b43a08992f61fa1a5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Responses 请求体构造与兼容归一(2417 行):出站 URL 校验(security.url_allowlist)、端点拼接(平台感知 /responses)、compact 子路径白名单化、OAuth/WS/透传三类兼容管线(prompt→input、internal 字段剥离、孤儿工具输出、schema、图像工具、压缩触发器顺序)、加密推理项的 trim/drop 两档清理、store=false 重放归一、reasoning effort 提取与归一(max→xhigh 按模型族)、fast policy(service_tier 过滤/阻断/强制 priority,组级 ForceOpenAIFast,WS response.create 帧)。下游 delta(±386):新增 normalizeOpenAICompatibleResponsesReasoningSummary(目的地契约,extra 可覆盖)、usesOfficialOpenAIResponsesInputContract(以具体目的地而非 openai 标签判定契约)、各 *ForModel 变体(以解析后上游模型应用兼容规则,Astra 豁免 reasoning.mode)、WS 透传只跑选定两条规则、删除 deriveOpenAIReasoningEffortFromModel(模型别名不再当作已达上游的 effort 证据)、compaction/compaction_summary 加密项纳入清理、supportsOpenAIReasoningEffortMax 扩展模型族。全部为协议兼容与策略执行机制;模型族能力表是协议适配提示,不是插件目录再实现(与既定 context-capacity 政策一致)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: normalizeOpenAICompatibleResponsesReasoningSummary L66-L110 (strict https/v1/responses target gate + ResolveReasoningSummaryMode), usesOfficialOpenAIResponsesInputContract L536-L552, normalizeOpenAIResponsesReasoningModeForModel L1180+ (Astra exemption), normalizeOpenAIWSPassthroughSelectedCompatibilityForModel L1221-L1271 (selected rules only on opaque WS history), normalizeOpenAIPassthroughOAuthBodyForModel L1435+, removed deriveOpenAIReasoningEffortFromModel/explicitRequestedReasoningEffortFromBody (wire-only effort recording, extractOpenAIReasoningEffortFromBody L1561), isOpenAIEncryptedPortableContinuationStateInputItem rename covering compaction items L433-L441, supportsOpenAIReasoningEffortMax families L2382-L2417", - "Security-relevant mechanics verified: validateOutboundURL enforces cfg.Security.URLAllowlist L33-L45; sanitizedUpstreamPathSuffix double-gates compact suffixes (openAIResponsesRequestPathSuffix L800-L830 + appendOpenAIResponsesRequestPathSuffix fallback); no plugin-domain pricing/catalog/identity decisions made in this file", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_request_body_reasoning_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1aaf8ea62a1839f5523cb12781876d1c7c1bf9b7917d0e7d5d673ebe2a0459e5", - "review_fingerprint": "1aaf8ea62a1839f5523cb12781876d1c7c1bf9b7917d0e7d5d673ebe2a0459e5", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "加密推理/压缩项清理与重放归一的单测。下游 delta(±94)证明三组下游行为变化:(1) SanitizeOpenAICrossModeFailoverReasoning 现在连同 compaction/compaction_summary 加密状态项整体删除,但保留无法与输出对安全拆分的加密 function_call 载体,且空/null/非串 encrypted_content 载体一律保留(新 PreservesEmptyCarriers);(2) 原生 API-key store=false 重放不再删 rs_ id/补 summary/删 item_reference——TestNativeAPIKeyReasoningReplayPreservesStoreFalseHistory 断言 changed=false 字节原样,历史完整保留(经 normalizeOpenAIResponsesWebSocketCompatibilityBody 入口);(3) 大整数经 UseNumber 不被 float64 圆整。其余(trim content:null、compaction 表、parallel_tool_calls、none effort 按账号保留、reasoning content 仅对 OpenAI 目的地剥离)与上游一致。核心续写状态机制的正确性测试;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: DropsWholeEncryptedItem extended with compaction/compaction_summary/function_call carriers (L143-L169), new PreservesEmptyCarriers L179-L201, store-false replay tests renamed+inverted to preserve history: NativeAPIKeyReasoningReplayPreservesStoreFalseHistory L237-L258 asserts changed==false and rs_encrypted id kept (upstream version stripped id and set summary []), CompactDoesNotProvePriorStoreMode L272-L280", - "Also proven: PreservesLargeIntegers L211-L222 (const 9007199254740993 not rounded), FilterOpenAIResponsesNoneReasoningEffortForAccount matrix L306-L383 preserving none for OpenAI-native/passthrough accounts", - "Statically read only; assertions were not executed." - ] - }, - { - "path": "backend/internal/service/openai_gateway_response_flush_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e49c5967e3691decf068fb45a56b27c5be8a5f99eaa22bc8b6befb0f911639c5", - "review_fingerprint": "e49c5967e3691decf068fb45a56b27c5be8a5f99eaa22bc8b6befb0f911639c5", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Forward 路径(handleStreamingResponse)流式 flush/终止语义单测:事件边界 flush、突发批量不增 flush、EOF 残留冲刷、pre-output preamble 缓冲可无写出 failover、keepalive 立即 flush 且不劈开未完事件(填满 16 槽扫描队列验证)、断连后仍拉完 usage。下游 delta(±235)删除四个裸 error 时序合成测试,改为证明下游新语义:ContinuationFailedEventIsNeverForwarded——previous_response_not_found 无论输出前后都不透传给客户端,输出前变为 continuation-state failover(不换号、不计调度失败);裸 error 等待权威 response.failed 的 usage、无终态时合成恰好一个 response.failed 并吞掉 [DONE];RejectsDoneWithoutAuthoritativeTerminal——[DONE]/无效 JSON 不能充当语义终止;TerminalBoundaryReturnsBeforeReadError——终态边界先于读错误返回。核心流机制正确性;仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: removed BareErrorFollowedByCompleted/CompatibleAPIKeyDoesNotUseCodexBareErrorSynthesis/RecentBareErrorAllowsCompleted/BareErrorTimeoutSynthesizesFailed; added ContinuationFailedEventIsNeverForwarded L455-L500 (IsOpenAIContinuationStateUnavailable, ShouldRetryNextAccount false, body free of previous_response_not_found), RejectsDoneWithoutAuthoritativeTerminal L502-L536, TerminalBoundaryReturnsBeforeReadError L270-L282, reworked bare-error subtests L392-L453", - "Also proven: keepalive flushes ':' immediately L325-L343, KeepaliveDoesNotSplitOpenEvent gated 17-line partial event L345-L390, ClientDisconnectStillDrainsUsage 7/5/2 cache tokens L538-L555", - "Statically read only; assertions were not executed." - ] - }, - { - "path": "backend/internal/service/openai_gateway_response_handling.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "fd16fd3bfb2f27f1c105472b5e3f127f7488f3d0a3f6c70d4d2487e65af56e57", - "review_fingerprint": "fd16fd3bfb2f27f1c105472b5e3f127f7488f3d0a3f6c70d4d2487e65af56e57", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Forward 路径响应处理主文件(2843 行):流式 SSE 状态机(guarded first-output 暂存、TTFT 双口径、keepalive/间隔超时/首输出超时三计时器、事件级 flush)、非流式 JSON 与 SSE→JSON 提取、usage 解析(多路径候选含 data 包装、缓存/图像 token、xAI 独立 reasoning token)、终局输出重建与 compaction item 补齐(#3777/#3887)。下游 delta(±1218):Codex turn-state HTTP 暂存/提交与溯源(stage/commitOpenAIHTTPResponseTurnState)、openAIHTTPAuthoritativeTerminalEvent 严格终止判定、openAIHTTPReasoningRejectionBeforeOutput(签名拒绝→请求级 continuation 错误,不入账号池重试)、readOpenAIResponsesHTTPBody(限长读取,权威 SSE 终态即返回不等 EOF)、sanitizeOpenAICyberPolicyFailedEvent(改写为中性可重试失败)、裸 error 合成 response.failed、空 completed 静默拒绝切号(#5009)、容量降载码改写、Grok 空闲超时+短冷、opaque 绑定与 Cindy 余额终止 failover(委派共享 helper)、拒答改写流。usage-parse 失败报错行为与上游一致(上游 L1630 同文案,非回归);bindHTTPResponseAccount 以 WithoutCancel+限时预算把 responseID/owner 绑到实际服务账号;defer 关 body、扫描缓冲池化、断连后继续排水。无插件域规则再实现。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: added stageOpenAIHTTPResponseTurnState/commitOpenAIHTTPResponseTurnState L50-L88, writeOpenAIHTTPResponseData short-write check L90-L104, first-output staging + guarded scanner + timeout L110-L360 (openAIFirstOutputStage, firstOutputScanGuard, newOpenAIFirstOutputTimeoutError L1290-L1302), bare-error synthesis via buildOpenAIResponseFailedSSE in finalizeStream L495-L520, openAIHTTPAuthoritativeTerminalEvent L1900-L1925, openAIHTTPReasoningRejectionBeforeOutput L1931-L1968, readOpenAIResponsesHTTPBody bounded terminal-aware reader L1994-L2050, sanitizeOpenAICyberPolicyFailedEvent L2320-L2395, empty-completed #5009 failover L1035-L1043; moved out: effectiveOpenAISSEEventType/mergeOpenAIUsageNonZero/missing-usage sampler/response-owner bind helpers", - "Checks: usage-parse failure on JSON without usage identical to upstream aea725f (its L1630) - not a downstream regression; bindHTTPResponseAccount uses context.WithoutCancel + openAIWSStateStoreRedisTimeout budget and binds owner (user/apiKey) too L1657-L1700; guard-mode event queue bounds retention (~16MiB comment L1178-L1181); scanBuf pooled in both sync path and reader goroutine", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_responses_anthropic_native.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5b9c7f20af7d3dadad146a26a36ac7cadfdad3fc7de46f05dd98dc0f3f4f42ad", - "review_fingerprint": "5b9c7f20af7d3dadad146a26a36ac7cadfdad3fc7de46f05dd98dc0f3f4f42ad", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI /v1/responses 客户端×国产供应商原生 Anthropic 端点的交叉转换路径:请求 Responses→Anthropic 单转换、响应 Anthropic 事件→Responses 事件状态机;上游恒流式,非流式由缓冲路径组装;idle pump 限定上游挂死;断连后继续排水至流终(末尾 message_delta 才带 output_tokens,防漏计)。下游相对 aea725f 仅 4 行:readOpenAIUpstreamError(resp,c)/failoverOpenAIUpstreamHTTPError 去 upstreamMsg 参数的错误读取签名重构(与本切片其他文件同一重构)。宿主协议机制,无插件域业务规则。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: only L129-L137 error-read signature refactor; rest identical to upstream blob fa2e190b9", - "Anchors: forwardResponsesViaNativeAnthropic L37-L143 (client tool lowering + model mapping + pre-filters), buffered assembly with anthropicNativeLinePump idle bound L148-L300, streaming conversion drains after disconnect for usage L343-L494 with finalize passing tool-name reversal", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_responses_chat_fallback.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a9e536c70eea57f27c5c9e19eb61a99f7a5f7f9f38c3e1d714e307f5d6f4fa9f", - "review_fingerprint": "a9e536c70eea57f27c5c9e19eb61a99f7a5f7f9f38c3e1d714e307f5d6f4fa9f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "/v1/responses 客户端经仅支持 chat/completions 上游的回退路径(564 行,审阅冻结后字节 sha a9e536c7…,含冻结提交 63a98c8cc 的快照绑定)。下游 delta:(1) compact 参数与业务系统提示词——转换前 restoreBusinessSystemPromptBeforeConversion、转换后对 CC body applyBusinessSystemPromptForRequest+cache key 重写(均经扩展宿主委派);(2) resolveOpenAIForwardModelContext(Cindy 目录快照,插件提供)+legacy Laxa live 映射(在普通 model_mapping 之后,保持优先级);(3) ResponsesConversionError→请求级 failover(不惩罚账号健康);(4) 流侧 pendingEvents 首输出前缓冲(pre-output failover)、scan.Err 输出后以 upstream_stream_failed 终态收尾且不暴露重放候选、工具参数校验仅在 finish 映射 completed 时执行(截断→response.incomplete)、终态 failed 不发 [DONE] 且作错误返回、chatChunkStartsResponsesOutput 要求非空 delta;(5) 非流式 failed 状态转协议失败。reasoning 明文缓存(7 天 TTL,detached ctx,fail-open)与 DeepSeek 占位为上游已有内容。协议机制,域数据经插件快照。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Post-freeze bytes reviewed (564 lines, sha256 a9e536c70eea...); delta vs aea725f: business prompt restore/apply L34-L39+L125-L138, resolveOpenAIForwardModelContext L85-L88 + legacy Laxa mapping L98-L104 (cindyLegacyLaxaLiveUpstreamModel -> plugin-served snapshot), conversion error as request-scoped UpstreamFailoverError L76-L80, pendingEvents pre-output buffering L248-L289, scan.Err finalize-with-failure L291-L299, ValidateToolCallArguments gated on completed finish L315, terminal failed suppresses [DONE] and returns terminalErr L336-L363+L381, stricter chatChunkStartsResponsesOutput L384-L394", - "Upstream-preexisting (not delta): reasoning cache recache/get/set with 7d TTL and detached 2s ctx L405-L500, DeepSeek reasoning placeholder helpers L502-L564", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_responses_chat_fallback_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b99f19496453ce0d13d3ba36045e422a6569a8211b02e1f8e221152b2d9ff6cf", - "review_fingerprint": "b99f19496453ce0d13d3ba36045e422a6569a8211b02e1f8e221152b2d9ff6cf", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "responses→CC 回退路径单测。下游 delta(±19,四处行为反转)证明下游修复:(1) 显式 reasoning.effort=none 在 OpenAI 平台账号上保留并透传(原测试断言被剥离)——对应 shouldPreserveOpenAIResponsesNoneReasoningEffort 放宽;(2) finish_reason=length 截断的工具参数不再报 invalid JSON 错误,而是发 response.incomplete 终态且 NoError——对应工具参数校验仅在 completed 时执行;(3) 纯 reasoning 流保留为 reasoning_summary_text.delta,不再合成 output_text;(4) forwardOpenAIPassthrough 签名适配。其余(路由与转换、service_tier 保留与上游降级观测、passthrough 标志回退用账号映射、auto 支持账号仍走 /v1/responses、reasoning 缓存写入/回查回注)与上游一致,统一静态验读。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: PreservesExplicitNoneReasoningEffort L64-L94 (was Omits...; now asserts reasoning_effort==none on wire and in result), MarksTruncatedToolsIncomplete L186-L228 (was Rejects...; now NoError + response.incomplete + no response.completed), ReasoningOnlyStreamPreservesReasoningWithoutAnswer L230-L264 (NotContains output_text.delta, Contains reasoning_summary_text.delta)", - "Also proven statically: reasoning cache write side (exactly one item, think first) L349-L399 and restore side (encrypted-only item gets cached thinking from lookup, plain summary re-cached) L401-L446", - "Statically read only; assertions were not executed." - ] - }, - { - "path": "backend/internal/service/openai_gateway_responses_client_tools_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "595bd9e8e4a93ba1d8213df64bfa91054c3d351409e2f544085993a52b22c59c", - "review_fingerprint": "595bd9e8e4a93ba1d8213df64bfa91054c3d351409e2f544085993a52b22c59c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Responses 客户端工具(custom/tool_search/namespace)降级为 function 工具转发并回程还原的单测:namespace-only 请求不改写、尾随 JSON 拒绝、tool_search 发现输出降级、context 映射清理、DeepSeek 原生/adaptive Responses 与 OpenAI API-key 透传的流式/非流式还原、compact 跳过适配、content parts 数组原样到达上游。下游 delta 仅 3 处 forwardOpenAIPassthrough 调用签名适配(去掉一个 nil 参数,随 passthrough.go 重构)——纯机械改动,不证明行为修复,测试实质与上游一致。静态验读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S10-svc-openai-gateway-2-review.json", - "Delta vs aea725f: only 3 call sites L242/L268/L298 drop one nil arg from forwardOpenAIPassthrough (matches the source-side signature change in openai_gateway_passthrough.go); all assertions otherwise byte-identical to upstream blob 1c9bdd6bc", - "Behaviors read: adaptOpenAIResponsesClientTools trailing-data rejection L63-L78, tool_search discovery lowering shared with Grok L80-L98, custom_tool_call restoration streaming/non-streaming L111-L192+L225-L308, compact path skips adaptation L194-L223", - "Statically read only; assertions were not executed." - ] - }, - { - "path": "backend/internal/service/openai_gateway_scheduling.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "fbd447aac4482f281e6c73573dab6f5b301d4e9ff25fe663f31b6a559fc6fe43", - "review_fingerprint": "fbd447aac4482f281e6c73573dab6f5b301d4e9ff25fe663f31b6a559fc6fe43", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_gateway_search_surcharge_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b5e673ec1b23488f8c3311fedcc69bfc09c8b6647f6c7409763fc312f2e7f4fe", - "review_fingerprint": "b5e673ec1b23488f8c3311fedcc69bfc09c8b6647f6c7409763fc312f2e7f4fe", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "搜索按次计费单测: 断言 calculateOpenAIRecordUsageCost 的 search 附加费与 token 费相加 (1000in/500out + 100次×$10/1k = 1.0105)、空模型候选时仅按次计费、token 定价错误不被 search 吞掉 (返回 err 而非 0 元账单), 以及 groupMediaPricingLooksIncomplete 的完备性判定。下游相对上游仅在 3 个调用点 (L33/L66/L112) 补一个 nil 实参适配 calculateOpenAIRecordUsageCost 新增的 account 参数, 断言语义零变化, 不证明下游修复。测试仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L125): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git diff aea725f: 仅 3 处 +nil 实参 (签名适配), 无断言改动", - "被测 calculateOpenAIRecordUsageCost/groupMediaPricingLooksIncomplete 位于 openai_gateway_usage.go 宿主计费路径", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "60dff85f2074c9fd754f56597aa23f95703be5f8e66786fdcf07da64fe1debef", - "review_fingerprint": "60dff85f2074c9fd754f56597aa23f95703be5f8e66786fdcf07da64fe1debef", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 网关服务的类型与装配中枢: 请求头白名单、Codex 限额快照结构、OpenAIForwardResult、服务结构体/构造器、WS 重试退避与指标、codex_cli_only 诊断日志、GetAccessToken。下游相对上游: 白名单去掉 x-codex-installation-id 并放行 session-id/thread-id/x-client-request-id (Codex 身份指纹整改, 与 buildUpstreamRequest 测试一致); 快照增加 PrimaryResetAt/SecondaryResetAt; OpenAIUsage 增加 5m/1h 缓存创建桶; ForwardResult 增加 UsageInputTokensExcludeCache/UpstreamTerminalStatus/ImageInputCount; SetActualOpenAIUpstreamEndpoint 改为总是覆写以防账号 failover 间端点残留 (正确性改进); 结构体新增 businessPromptService (prompt-skills 钩子)/cindyHealth/usageCache/usageCommitObserver 与 Cindy 运行时封禁 map 及 4 个 setter; SetCodexForceCLIEnabled 进程级开关; Cindy 数据面默认关闭 image_generation 注入。均为宿主机制与插件挂点。仅静态阅读, 未执行测试。", - "evidence": [ - "Full-file static review (L1-L1334): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git diff aea725f (268 行): 白名单 hunk L74-L110, snapshot ResetAt L129-L140, ForwardResult 新字段 L242-L318, SetActualOpenAIUpstreamEndpoint 总是 Set (L353-L360), struct+setter hunk L484-L564, SetCodexForceCLIEnabled (L595), isCodexImageGenerationBridgeEnabled 的 IsCindyRuntimeCompatibleAPIKeyAccount 分支 (L682-L689), WS bootstrap 日志加 CindyHTTPToWSV2Enabled (L779-L783)", - "accountWriteThrottle.lastByID 有 >4096 清理 (L441-L448), 无无界缓存; codex_cli_only 拒绝日志走白名单+256 字节截断, prompt_cache_key 仅记 sha256 前 8 字节 (L1231, L1241-L1263), 无秘密外泄", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_service_codex_cli_only_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "932f9668156cbdb06b49cd11ed724035947753d59ea432e3bb8400ea5ed67a60", - "review_fingerprint": "932f9668156cbdb06b49cd11ed724035947753d59ea432e3bb8400ea5ed67a60", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "codex_cli_only 检测与上游错误分类的单测。下游新增/改写的断言证明三组核心修复: (1) 408 在 shouldFailoverUpstreamError/shouldFailoverOpenAIUpstreamResponse/shouldFailoverOpenAIPassthroughResponse 三条路径均触发换号; (2) continuation-state 错误 (previous_response_not_found/invalid_encrypted_content, 含 502/403 包装与窄短语兜底) 不换号、请求级 scope、不罚账号健康、客户端统一 400+固定文案; (3) instructions-required 用例由上游 400 原样回写改写为 request_rejected 终态: handler 负责渲染, err 文本与 ContinuationDiagnostic 不含上游 message 及请求体中的 access_token (只保留 type/code/param 结构字段), 防泄漏。另加 pool_mode_retry_status_codes 凭据使 400 容量错误按池策略同号重试。被测对象全部是 core 转发/错误分类。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L610): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git diff aea725f: +TestOpenAIRequestTimeoutTriggersFailover (L367-L374), +TestOpenAIContinuationStateErrorsStopAccountFailover (L376-L431), Forward_LogsInstructionsRequiredDetails 改写为 Forward_RecordsSafeInstructionsRequiredDiagnostic (L433-L509, NotContains secret-token/Missing required parameter), pool_mode_retry_status_codes (L590-L594)", - "断言锚点: classifyOpenAIContinuationStateError/newOpenAIUpstreamFailoverError/shouldFailoverOpenAIUpstreamResponse (openai_gateway_upstream_errors.go), OpsUpstreamErrorEvent.ContinuationDiagnostic", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_service_codex_snapshot_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c7b7a2f90ef8a55ca72e953fd8ac8dbb2b51118a21ff8d5b2d5d1fdf1455e724", - "review_fingerprint": "c7b7a2f90ef8a55ca72e953fd8ac8dbb2b51118a21ff8d5b2d5d1fdf1455e724", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Codex 限额快照落库单测: codexSnapshotBaseTime 的 updatedAt/兜底选择、codexResetAtRFC3339 负秒钳到基准、buildCodexUsageExtraUpdates 写 codex_5h/7d_reset_at 绝对时间与 updatedAt 优先、used_percent 不反转 (issue #2994 回归护栏, 上游已含)、nil 快照返回 nil、无窗口字段时不写 reset_at。下游相对上游仅在 L55/L67 两处 t.Fatal 后补 return (staticcheck 修正), 断言零变化, 不证明下游修复。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L227): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git diff aea725f: 仅两处 +return, 无断言改动", - "被测 buildCodexUsageExtraUpdates/codexSnapshotBaseTime/codexResetAtRFC3339 位于 openai_gateway_usage.go 宿主配额快照机制", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_service_hotpath_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4daca8bc8c2f05e7ae0d9125340d3b96f6d8efc89137ab3049ec7af120da3f55", - "review_fingerprint": "4daca8bc8c2f05e7ae0d9125340d3b96f6d8efc89137ab3049ec7af120da3f55", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Forward 热路径单测。下游改写把上游『invalid_encrypted_content 时剥离加密历史/compaction 后同号重放 (2 个上游请求)』反转为『终态 continuation-state 错误: 恰好 1 个上游请求、请求体逐字节不变、不换号、不罚健康、response.failed (含 SSE 首事件与包装码) 不得被改写成成功』, 共 6 个新/改测试钉死该修复; 新增 Cindy Laxa 账号顶层 live image ID 必须走 Luna 控制器 (Forward 直接报错且不出网) 的护栏; reasoning effort 修正: none→minimal、x-high→xhigh、max/minimal 保留、缺字段不再从模型后缀 (-high) 推导。其余 (RequestView 补丁/重复键取首值、max_tokens→max_output_tokens 归一化 #4417、空 base64 图剔除、大数字 raw 保留) 与上游一致。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L1285): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git diff aea725f: HTTPRetryRecoveryDoesNotDecodeBeforeError/DropsCompaction 改写为 *StopsWithoutMutatingRawInput/*StopsWithoutDroppingCompaction (upstream.bodies 断言从 2 变 1 且 JSONEq 原请求体), +Wrapped/ResponseFailed/StreamingResponseFailed/ToolOutput 四个终态用例 (L687-L883), +TestForwardCindyResponsesTopLevelLiveImageIDUsesLunaController (L547-L575), effort 期望 none→minimal (L141) 与后缀推导用例删除", - "断言锚点: UpstreamFailoverError.IsOpenAIContinuationStateUnavailable/ShouldRetryNextAccount/SuppressAccountHealthPenalty; OpenAIReasoningSignatureRecoveryEnabledExtraKey=false 时同样不重放 (L716)", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6a942b7293bdfd01117b48a8eecd385122a489a594407dabe968a7c8c63c414e", - "review_fingerprint": "6a942b7293bdfd01117b48a8eecd385122a489a594407dabe968a7c8c63c414e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 网关服务主测试 (4025 行, 全文已读): 调度选择/粘性清理/负载感知、流式终态与 failover、SSE 用量解析、buildUpstreamRequest 身份头、cyber_policy 标记。下游 delta (39 行) 证明的行为变化: (1) handleSSEToJSON 无终态帧由『保留 SSE 体+零用量成功』改为『502 JSON 错误+nil usage』(缺终态不是零成本成功); (2) 透传流 response.incomplete 由静默成功改为返回含 incomplete 的错误但保留 usage 供计费; (3) OAuth Messages 桥不再发下划线 Session_Id 头、X-Codex-Installation-ID 不再作为请求头转发 (只留 body client_metadata), 与真实 Codex 形态对齐; (4) stub cache 增加 DeleteSessionAccountIDIfMatches 与 ErrStickySessionNotFound 哨兵, 适配比较删除接口; 其余为 CurrentConcurrency 字段适配、failoverOpenAIUpstreamHTTPError 签名去 message 参数、两处 t.Fatal 后 return 与 SSE fixture 空行。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L4025, 9 个顺序分块读到 EOF): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git diff aea725f: TestOpenAIStreamingPassthroughResponseIncompleteWithoutDoneMarkerStillSucceeds 改名为 ...IncompletePreservesFailureAndUsage 且 NoError→ErrorContains \"incomplete\" (L2731-L2764); TestHandleSSEToJSON_NoFinalResponseKeepsSSEBody 改为 ...RejectsIncompleteStream (L3843-L3866); Session_Id/X-Codex-Installation-ID 断言取反 (L3202, L3251); +DeleteSessionAccountIDIfMatches stub (L792-L797)", - "断言锚点: handleStreamingResponse/handleStreamingResponsePassthrough/handleSSEToJSON/buildUpstreamRequest/parseSSEUsage; 粘性清理断言经 stubGatewayCache.deletedSessions 计数", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_service_tool_correction_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "82a254c51eff56d50de571dc7b050abd307cacdaaea5898b5c8c93bd2f94ac27", - "review_fingerprint": "82a254c51eff56d50de571dc7b050abd307cacdaaea5898b5c8c93bd2f94ac27", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "CodexToolCorrector 集成单测: 响应体内 apply_patch→edit、update_plan→todowrite 的工具名修正、无需修正时字节不变、修正统计计数。该修正器与本测试在上游 aea725f 中已存在; 下游 delta 仅 L88 一处 t.Fatal 后补 return (lint 修正), 不证明下游修复。修正逻辑本体 (CodexToolCorrector) 属 core 转发链路的 Codex 工具名适配。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L134): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git diff aea725f: 仅 L88 +return, 无断言改动", - "被测 correctToolCallsInResponseBody/CorrectToolCallsInSSEData/GetStats 由 NewCodexToolCorrector 提供 (core 服务层)", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_turn_state_commit_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f870209dc134ab2e5290e553dd6cf1b0cd29092534f86a6168dfa3861b41afd7", - "review_fingerprint": "f870209dc134ab2e5290e553dd6cf1b0cd29092534f86a6168dfa3861b41afd7", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游全新测试文件 (上游 ls-tree 无此路径, 整文件即 delta)。钉死 x-codex-turn-state 出站守卫的提交边界: openaiCodexTurnStateOrigins 注册表只在下游写成功后才把会话 seed 的铸造账号切换为本次服务账号 (下游写失败保留旧 owner), 上游响应不带 state 头时清除该 seed 的 origin; 流式/非流式/透传流式/透传一元四条路径共用同一边界。防跨账号 turn-state 回带 (openai_codex_turn_state.go 的守卫状态机) 属 core 协议正确性。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L211): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git ls-tree aea725f 无此路径, 新增文件即全量 delta; 断言 requireOpenAITurnStateOrigin 检查 svc.openaiCodexTurnStateOrigins 中 accountID 的保留/切换/删除 (L94/L104/L114-L115)", - "覆盖 handleStreamingResponse/handleNonStreamingResponse/handleStreamingResponsePassthrough/handleNonStreamingResponsePassthrough 四路径, 写失败用 failingGinWriter 注入", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_upstream_errors.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2835d1958f662ec17ffda26e3c8df4a38fe451ada9da9ffe9228fdabd6fc1a75", - "review_fingerprint": "2835d1958f662ec17ffda26e3c8df4a38fe451ada9da9ffe9228fdabd6fc1a75", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 上游错误分类与 failover 策略中枢。下游相对上游: shouldFailoverUpstreamError 增加 408; 新增 continuation-state 错误族 (classify/is/FromFailedEvent, 含 thinking_signature_invalid 仅认结构化拒绝) 与请求级终态 NewOpenAIContinuationStateUnavailableError (400+固定文案, 不换号不罚健康); 新增残余 400 分类器 classifyOpenAIRequestRejection + NewOpenAIRequestRejectedError (净化终态, 不带上游 body, 保留 RateLimitService 的两个认证 400 特例与 512 字节边界); isOpenAIReportedUpstreamFailure 识别代理自报 400 upstream_error; isOpenAIRequestBudgetRejection (官方 API-key balance_insufficient 402/403 换号); Cindy 结构化 429 余额枯竭在 handleErrorResponse/handleCompatErrorResponse 最前面消费 (handleCindyBalanceHTTPFailover → 账号级封禁+净化, 实现依托 cindy_balance.go/openai_cindy_http_wsv2.go); 错误体经 rewriteBusinessSystemPromptJSON* 重写 (prompt-skills 钩子); 确定性 400 改为回写真实状态码+code/param 而非 502 重包 (#5479); newOpenAIAccountFailoverError*/access-state/capacity-shed 助手迁至 openai_v183_compat.go (rg 确认仍单一定义, 无二执行体)。文件本体为宿主协议错误机制。仅静态阅读, 未执行测试。", - "evidence": [ - "Full-file static review (L1-L1117): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git diff aea725f (558 行): +isOpenAIRequestScopedSafetyRejection/continuation-state 前置于 shouldFailoverOpenAIUpstreamResponse (L249-L307), +classifyOpenAIContinuationStateError (L398-L446), +classifyOpenAIRequestRejection (L475-L522), newOpenAIUpstreamFailoverError 的 continuation 短路与 upstream_reported_failure 典型化 (L560-L579), +handleCindyBalanceHTTPFailover (L684-L708), handleErrorResponse 的确定性 400 直写 (L897-L913 注释含 #5479 依据)", - "call-chain: isOpenAIHTTPUpstreamAccessStateError/openAICapacityShedClientMessage/newOpenAIAccountFailoverError 现定义于 openai_v183_compat.go L216/L220/L341; writeOpenAIUpstreamClientError 于 openai_upstream_client_error.go; cyber 路径与上游行为一致 (无 MarkResponseCommitted 的写法上游即如此, 非下游回归)", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_upstream_errors_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d7cb85bbeb13921bcdbc4a934fad71c378c8871f51ec0157b7df127e6ff50123", - "review_fingerprint": "d7cb85bbeb13921bcdbc4a934fad71c378c8871f51ec0157b7df127e6ff50123", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游全新测试文件 (上游无此路径)。钉死残余 400 分类器: request_validation (有 param 或结构化 validation type/code) 与 unclassified_bad_request 的边界、18 个专属策略 (continuation/context/capacity/safety/model_not_found/access-state/reported-upstream/非 400 状态) 均返回空串不落入残余分类; 认证 400 两特例 (organization disabled/identity verification) 保留且回显字段与超 512 字节的消息不算数; NewOpenAIRequestRejectedError 的请求级 scope、NextAccountStop、不罚健康、空 ResponseBody 与 header Clone 快照语义; openAIContinuationStateErrorFromFailedEvent 对嵌套/顶层错误码分类而普通 server_error 不命中。全部为下游新增错误策略的证明。仅静态阅读, 未执行。", - "evidence": [ - "Full-file static review (L1-L130): artifacts/evidence/v027-claude-S11-svc-openai-gateway-3-review.json", - "git ls-tree aea725f 无此路径, 新增文件即全量 delta; 22 个表驱动用例 (L18-L39) + 认证特例 4 例 (L49-L64) + 终态错误字段断言 (L66-L86)", - "被测 classifyOpenAIRequestRejection/NewOpenAIRequestRejectedError/openAIContinuationStateErrorFromFailedEvent 均在同切片 openai_gateway_upstream_errors.go", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_gateway_usage.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e1e38a1adcd4b09f2f90eeb46f4d90092377c32bbc4679041fcff7e5518bc17a", - "review_fingerprint": "e1e38a1adcd4b09f2f90eeb46f4d90092377c32bbc4679041fcff7e5518bc17a", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_guardian_affinity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b1bd1f5cee56e25c88a439113a67509eae19237fa869040eb0c730ca348f1a44", - "review_fingerprint": "b1bd1f5cee56e25c88a439113a67509eae19237fa869040eb0c730ca348f1a44", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "guardian/review 子代理亲和调度测试:无歧义 lineage 才建立亲和(模型+subagent 头+parent 线程一致,WS 信封 metadata 亦可;冲突/缺失即放弃)、三种调度模式下子请求选中父账号绑定(GuardianParent 层)、跨组或父账号被排除时回退且绝不删除父绑定、哈希碰撞不覆盖父绑定、分组 RequirePrivacySet 跳过未设隐私账号且不全局标错、previous_response 绑定尊重分组与隐私(策略查失败 fail-closed、瞬时 miss 保留绑定)、simple 模式忽略分组成员约束。下游相对上游仅 2 行:isOpenAIAccountRequestRuntimeBlocked 增加第三个 bool 实参的签名适配,断言语义不变,故记 reference。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:仅 L279/L381 两处调用补第三参 false", - "被测:WithOpenAIGuardianParentAffinity/SelectAccountWithScheduler(ForCapability)/SelectAccountByPreviousResponseID(openai_guardian_affinity.go 与调度器,上游已有)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_http_response_owner_bridge_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "21e12b340d52dcfa512f8c558d6eeb5930dd07b76ab72a0c7ee8826c755cec4b", - "review_fingerprint": "21e12b340d52dcfa512f8c558d6eeb5930dd07b76ab72a0c7ee8826c755cec4b", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "全文复核48行fake WS dialer/conn fixture:真实HTTP Forward→WSv2成功结果既有account affinity不足以授权,新增HTTP owner登记由可信context供给;同user换key允许、body身份与不同group不继承。不调用原生WS公网或数据库。", - "evidence": [ - "artifacts/evidence/v027-astra-http-response-owner-review.json", - "Parent read the entire fixture and matched current SHA; only the report-specific targeted commands were run." - ] - }, - { - "path": "backend/internal/service/openai_http_terminal_boundary_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d6770ba8edd8720019bc190fe373e9589b5c0abcf8053302bf5225c3bdd7f4a4", - "review_fingerprint": "d6770ba8edd8720019bc190fe373e9589b5c0abcf8053302bf5225c3bdd7f4a4", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(295 行),锁定 HTTP /v1/responses 五种处理分支(native/native_async/passthrough/buffered/passthrough_buffered)的终止事件边界语义:收到权威终止事件(completed/incomplete/failed)立即返回并关闭上游 body、不等 EOF(阻塞 reader+3s 超时证明);终止事件自带 usage 权威覆盖进度快照、reasoning.mode 与大整数扩展字段保真;事件名不覆盖 payload 类型;缺失/畸形终止([DONE] only、未完 delta、trailing 垃圾)一律报错;invalid_encrypted_content/thinking_signature_invalid 的恢复信号仅在无输出前发出(有可见输出后不再签发、buffered 例外)且解析候选不消耗重试次数;仅发过 keepalive 注释时恢复保持私密(旧 response id 不外泄);恢复关闭或 ctx 取消时降级为不换号的终止错误且 ResponseBody 为空;读错误不派发未完帧;缓冲体上限与取消传播。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "全文件即下游 delta;锚点:不等 EOF L61-L113、权威 usage L115-L140、failed 保 usage L142-L174、恢复信号窗口 L194-L223、keepalive 私密 L235-L259、禁转号降级 L261-L282", - "被测:handleStreamingResponse(Passthrough)/handleNonStreamingResponse(Passthrough)/openAIHTTPAuthoritativeTerminalEvent/extractOpenAISSETerminalEvent/openAIHTTPReasoningRejectionBeforeOutput/readOpenAIResponsesHTTPBody(openai_gateway 系列)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_image_generation_controls_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "54f7c6c8c39d92abfa831621e7b92acf083f478ed4cbb867b6f4acf1eed77924", - "review_fingerprint": "54f7c6c8c39d92abfa831621e7b92acf083f478ed4cbb867b6f4acf1eed77924", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "图像生成能力门与 Codex image bridge 的核心网关测试(835 行,下游 +82)。上游已有:分组 AllowImageGeneration=false 时 403 拦截图像意图(模型/工具/tool_choice)但放行纯文本、bridge 注入矩阵(分组能力+全局开关+responses-lite 豁免)、显式工具 format 归一、账号策略剥离显式/命名空间图像工具、渠道>账号>全局覆盖优先级、compact 请求豁免注入、image_generation_call 计数与 image_tokens 提取、流式 status 归一为 completed、cyber 命中时从 response.failed 捕获真实 usage 计费。下游 delta 专证 Cindy 边界:第一类与 legacy Cindy 账号不继承全局 bridge 开关(新测试 +5 组优先级行),仅渠道显式 true 可启用、legacy 账号级覆盖仍权威、渠道 false 压制账号 true——图像业务规则归 image-tools/cindy 插件侧,这里证明宿主注入门的供应商边界修正。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:+TestOpenAIGatewayServiceForward_StrictCindySkipsGlobalCodexImageInjection(L139-L166)与优先级表 +5 行 Cindy 用例(L503-L555)", - "被测:isCodexImageGenerationBridgeEnabled/Forward 注入路径/normalizeCompletedImageGenerationStatus/handle*Response 图像计数(openai_gateway 与 images 系列)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_images.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "64649db5990868a8666467261fcf58490146f3d192d66a9bfc00065e98b052e4", - "review_fingerprint": "64649db5990868a8666467261fcf58490146f3d192d66a9bfc00065e98b052e4", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_images_incomplete_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a9196f632aec2c7d585a6fcf8c0f0a83327928c948b1209bcda90346eacae98b", - "review_fingerprint": "a9196f632aec2c7d585a6fcf8c0f0a83327928c948b1209bcda90346eacae98b", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "图像流 incomplete/无图失败分类的回归测试:response.incomplete(max_output_tokens) 记 502 可重试、content_filter 记 400 不重试、error/response.failed 老行为不变、无图诊断摘要(last_event/status/incomplete_reason/截断)、completed 无图软失败偏好同账号重试、模型文字拒绝按 400 content_policy 不重试且携带拒绝原因、文字兜底(未执行出图)记 502 image_generation_unavailable 且流式不提前 flush error、拆分安全拒绝仍 400 并送达流式客户端。下游相对上游仅 +2 行 t.Fatal 后补 return(nil 解引用防护)与 handleOpenAIImagesOAuthStreamingResponse 签名补一个 nil 实参,断言语义与上游一致,故记 reference。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S18-svc-openai-misc-1-review.json", - "diff vs aea725f:L22/L44 补 return;L207/L238 签名多一个 nil 参数;无断言变化", - "被测:extractOpenAIImagesUpstreamError/summarizeOpenAIImagesNoOutputBody/handleOpenAIImagesOAuth{Non,}StreamingResponse/extractOpenAIImagesModelRefusal(openai_images_responses.go 等,上游已有)", - "未执行测试。" - ] - }, - { - "path": "backend/internal/service/openai_images_responses.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "43b891a34778a3f28adddd85613c4ed778e83c2998edf210e38047d7d54dda45", - "review_fingerprint": "43b891a34778a3f28adddd85613c4ed778e83c2998edf210e38047d7d54dda45", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI Images 走 Responses 协议的核心网关实现:请求构造、SSE 图片抽取、错误分类、流式转发与 failover。下游相对上游 aea725f 新增 rawPayload 保留原始错误帧、Cindy 余额终态 failover 挂钩(handleCindyBalanceHTTPFailover/cindyBalanceHTTPResponseTerminalFailover/handleCindyBalanceTerminalEvent)、请求级安全拒绝直传、传输层错误统一交 handleOpenAIUpstreamTransportError、发送入口换为 doOpenAICodexUpstream(zstd 边界)并对错误体做 agent-identity 脱敏;这些都是宿主协议与账号池机制,Cindy 逻辑只是调用点。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: OpenAIImagesUpstreamError.rawPayload (L39, populated L640-643); cindy balance failover hooks in handleOpenAIImagesErrorResponse (L920-933), stream error/response.failed branch (L1583-1601), handleOpenAIImagesOAuthResponseError (L2113-2120, L2196-2205); doOpenAICodexUpstream switch at L1889; safety rejection + redactAgentIdentitySensitiveBody in forwardOpenAIImagesOAuth (L1903-1915).", - "Call chain: helpers live in core service files (cindy_balance.go L218, openai_gateway_upstream_errors.go L684, openai_codex_request_compression.go L128, openai_upstream_transport_error.go L108, openai_agent_identity.go L517); no plugin-side duplicate executor of this images protocol found.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_images_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3e3d67d164d8fc62c6ddd7b324a01039950dbb28fe1d756dbc49d3d6c3e1d4be", - "review_fingerprint": "3e3d67d164d8fc62c6ddd7b324a01039950dbb28fe1d756dbc49d3d6c3e1d4be", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Images 网关单测:断言请求解析(JSON/multipart、尺寸档位、能力要求)、Responses 请求构造(tool_choice/n/逐字 prompt)、SSE 流转换与断连排水、错误直传与 failover 分级、boundedJSONNonNegativeInt 防御性解析。下游相对上游仅新增两个测试:validateOpenAIImagesUpstreamModel 对 Cindy 严格映射与普通账号一律拒绝非原生 openai/google 前缀图片模型、validateOpenAIImagesModel 不把目录图片模型并入原生集合,证明的是核心图片模型校验边界。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: only TestValidateOpenAIImagesUpstreamModel_AllowsOnlyStrictCindyMappedImage and TestValidateOpenAIImagesModel_RecognizesCatalogImageWithoutChangingNativeSet added (L872-903); subjects validateOpenAIImagesUpstreamModel / IsNativeOpenAIImagesModel are core (openai_images.go L483-L514).", - "Assertions prove: cindy (PlatformCindy/ProviderProfileCindyLaxaV1) and ordinary accounts both get errors for gemini/openai-prefixed image models; native set unchanged (gpt-image-2 native, gemini-3-pro-image not).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_lineage_regression_helpers_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "dca6712ec7d6e2ba08b140cba30233bd2366da6b0b38d01fd2473a0c530fb1d0", - "review_fingerprint": "dca6712ec7d6e2ba08b140cba30233bd2366da6b0b38d01fd2473a0c530fb1d0", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "整文件为下游新增(31 行,//go:build unit):在测试构建里给 OpenAIGatewayService 补两个包装方法(markOpenAIWSInvalidEncryptedContentLineage / sessionInvalidEncryptedContentDigests),转调 core 的 openai_ws_state_store。生产代码已不再调用这两个包装或底层 Mark/Get 方法(invalid_encrypted_content 现走分类+重试路径),前者只被 openai_native_fidelity_test.go 使用,后者无任何调用者;本文件本身无断言。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream (git ls-tree upstream prints nothing; diff = 31 insertions). Wrappers call OpenAIWSStateStore.MarkSessionInvalidEncryptedContent / GetSessionInvalidEncryptedContentDigests (openai_ws_state_store.go L506/L549).", - "rg: markOpenAIWSInvalidEncryptedContentLineage only used by openai_native_fidelity_test.go L43; sessionInvalidEncryptedContentDigests has no callers; no non-test caller of the store session-invalid-digest methods remains.", - "No test execution; helper file compiles only under the unit build tag." - ] - }, - { - "path": "backend/internal/service/openai_live.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "8ed79718aad54e3a1bac1fbb546c57d0d688a51774e8b7c59e6d1f99e6ddb3cb", - "review_fingerprint": "8ed79718aad54e3a1bac1fbb546c57d0d688a51774e8b7c59e6d1f99e6ddb3cb", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI Live(Frameless/realtime)会话生命周期:创建上游 call、租约续期、sideband 代理、observer 兜底 finalize 与 usage 落库。下游相对上游 aea725f 仅在 CreateLiveCall 调度循环里补齐 runtime breaker 探针释放(各早退路径 ReleaseOpenAIRuntimeBreakerProbeForSelection)、上报调度结果(ReportOpenAIAccountScheduleResultForSelection 成功/失败)并把 session.model 提取上移复用为 scheduleModel。Live 不计费为已知状态、有 TODO 注释与测试锁定,非本次新增缺陷。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f confined to CreateLiveCall L147-227: breaker probe release on not-acquired (L176-181), lease-acquire failure (L198), non-failover create error (L207-210); schedule result reporting success L218 / failure L213 with account.GetMappedModel(scheduleModel); ReleaseFunc ordering moved after reporting.", - "Call chain: SelectAccountWithSchedulerForCapability / ReleaseOpenAIRuntimeBreakerProbeForSelection / ReportOpenAIAccountScheduleResultForSelection are core scheduling mechanisms; observer/finalize paths unchanged vs upstream.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_load_sticky_privacy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e0fe7a0ef9099b2de99080add38582b46187d79bd5250fd7e744f7ceb3e6ebb3", - "review_fingerprint": "e0fe7a0ef9099b2de99080add38582b46187d79bd5250fd7e744f7ceb3e6ebb3", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_model_mapping.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "b7606a7ba27ba3baf975b17bbc7d90f6466656c6cfe19d5cd9b438a3a5c8655e", - "review_fingerprint": "b7606a7ba27ba3baf975b17bbc7d90f6466656c6cfe19d5cd9b438a3a5c8655e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 转发模型解析:账号 model_mapping 解析、OAuth 空映射他厂模型黑名单、DeepSeek 可服务白名单、compact 专用映射。审阅的是 63a98c8cc 之后的冻结版本(slice 切片后变更):该提交新增 context 版解析器 resolveOpenAIForwardModelContext / resolveOpenAIForwardMappedModelsContext,把 Cindy 账号的映射绑定到请求期 CindyCatalogSnapshot(resolveCindyMappedModelSnapshot 依序查兼容映射、目标命中、可用映射、账号映射),并新增 compact 的 canonical 拼写回退。快照按请求捕获、不落 Account 状态,属宿主转发机制,Cindy 快照解析是其中的 provider 挂钩。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "SHA policy: file changed after slice cut and is FROZEN per Codex commit 63a98c8cc (fix(cindy): bind model mapping and pricing to request snapshots); reviewed the post-63a98c8cc on-disk bytes and recorded their self-computed sha256 b7606a7ba27ba3baf975b17bbc7d90f6466656c6cfe19d5cd9b438a3a5c8655e as content_sha256/review_fingerprint (slice had 312b73a0...).", - "Delta vs aea725f: +resolveOpenAIForwardModelContext/resolveCindyMappedModelSnapshot/resolveOpenAIForwardMappedModelsContext (L27-96) and resolveOpenAICompactForwardModelWithCanonical (L213-238); openAIOAuthForeignModelPrefixes + isOpenAIOAuthServableModel + deepseekServableModels blocks predate the freeze commit.", - "Call chain: context resolvers consumed across core forwarding (openai_gateway_forward.go, openai_gateway_chat_completions*.go, openai_gateway_messages*.go, openai_gateway_scheduling.go, openai_embeddings.go, model_rate_limit.go); no duplicate resolver found under plugins/cindy-provider.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_model_mapping_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0eb5be12eb65a68167b10a126d4b1c1acc2a9947615e20c0494e6dafbade2fa0", - "review_fingerprint": "0eb5be12eb65a68167b10a126d4b1c1acc2a9947615e20c0494e6dafbade2fa0", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_model_not_supported.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "33f0d9d7e2e490ee5a2c309e6d2e5141dbb73187df0921e0ed1a786e2edb2f97", - "review_fingerprint": "33f0d9d7e2e490ee5a2c309e6d2e5141dbb73187df0921e0ed1a786e2edb2f97", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "整文件下游新增:识别 Laxa/Cindy 风格上游 400 结构化 model_not_supported 错误的严格分类器(要求 type=model_not_supported、code=400、消息以 model 为主语且排除 parameter/feature 等限定词),并构造账号/模型对粒度的 UpstreamFailoverError(reason=upstream_400_model_not_supported,SuppressAccountHealthPenalty,30 分钟模型冷却常量),SSE/WS 事件复用同一匹配器防漂移。是宿主 failover/调度机制,Cindy 专属的启用门在调用方(shouldFailoverOpenAIUpstreamResponseForAccount 只对 legacy Laxa 账号放行)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream (not in upstream ls-tree). Key anchors: isOpenAIModelNotSupportedError L43-80 (strict structural match on error/response.error), hasModelNotSupportedMessage L82-105 (regex + qualifier rejection), newOpenAIModelNotSupportedFailoverError L110-125 (account-scoped, NextAccountRetry, stable client message, SuppressAccountHealthPenalty), IsOpenAIModelNotSupported L129-131.", - "Call chain: consumed by shouldFailoverOpenAIUpstreamResponseForAccount / stream+WS failover deciders and RateLimitService.HandleUpstreamModelNotFound (proven by openai_model_not_supported_test.go); client-facing message is a constant so upstream account state does not leak.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_model_not_supported_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "868e3fbda5fba9661564aa2ab75b2dabcafc45658975eb296fe8aa10da9a1be7", - "review_fingerprint": "868e3fbda5fba9661564aa2ab75b2dabcafc45658975eb296fe8aa10da9a1be7", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_model_reasoning_alias_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "50af7f6155a57ae02ed3cec5c1f00ff6847598e92c4b51db20893c943f7d797b", - "review_fingerprint": "50af7f6155a57ae02ed3cec5c1f00ff6847598e92c4b51db20893c943f7d797b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试:证明推理力度别名模型(gpt-5.6-sol-max 等)的显式解析边界(vendor 前缀/自定义名/日期后缀不猜测)、materialize 到实际协议字段(responses 用 reasoning.effort,chat 用 reasoning_effort)、显式 effort 优先于别名、组策略映射只应用一次(幂等,deny 拒绝)、codex OAuth transform 物化 wire 值且不改源 map、计费侧保留原始别名。主题是核心 openai_reasoning_effort_policy.go 与 openai_codex_transform.go,model-policy 插件下无重复实现。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream file. Anchors: TestMappedForwardReasoningAliasAppliesPolicyOnce L12-26 (idempotence + deny); TestResolveOpenAIModelReasoningAliasIsExplicit L28-55 (positive/negative alias table); TestMaterializeOpenAIModelReasoningEffortPreservesNativeIntent L84-121 (explicit/null/flat wins, unknown fields preserved, second pass no-op); TestApplyCodexOAuthTransformReasoningAliasMaterializesWire L160-188.", - "Subjects: resolveOpenAIModelReasoningAlias/materializeOpenAIModelReasoningEffort (openai_codex_transform.go L626/L680), materializeOpenAIForwardReasoningEffort/ApplyOpenAIReasoningEffortPolicy (openai_reasoning_effort_policy.go L436-L589); rg found no ReasoningEffort logic under plugins/model-policy, so no second executor.", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_models_list.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "4f9195b329bb8e0f47fb1a70f4cc33d691ba312def3a2b2aa8935a8189155963", - "review_fingerprint": "4f9195b329bb8e0f47fb1a70f4cc33d691ba312def3a2b2aa8935a8189155963", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "/v1/models 目录发现与投影:单账号目录抓取(OAuth 走 Codex manifest 缓存、APIKey 走标准端点)、manifest 字段重建(剥离 client-only 字段、保留 display_name)、账号映射投影与组白名单、pinned 与调度回退合并。下游相对上游新增上下文容量(context capacity)溯源管线:为 APIKey 目录建 codexModelCapacitySource、applyMappedModelsCapacityVisibility 把公共别名映射到可见/受保护模型集合而不改原始观测键、pinned 合并 capacity provenance 并经 ProjectOpenAIModelsListContextCapacities 输出。为宿主目录/容量机制。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: cloneOpenAIModelsResponse for OAuth manifest conversion (L37-40); capacitySources creation in APIKey fetch closure (L62-66); new applyMappedModelsCapacityVisibility (L277-330) + rawModelCapacitySourceIDs (L333-353); FetchPinnedOpenAIModelsList now applies visibility per account and merges provenance via mergePinnedModelsCapacityProvenance + ProjectOpenAIModelsListContextCapacities (L365-372, L409-419).", - "Matches the documented downstream context-capacity policy (/models capacity projection); visibility maps are bounded by catalog size per response, no unbounded growth; OAuth upstream slug stays protected after aliasing per comment L274-276.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_named_output_namespace_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "aff4ed342da1d0fc47c7e04fa028a35bbb570f7306c3282d3ab8669900316ffe", - "review_fingerprint": "aff4ed342da1d0fc47c7e04fa028a35bbb570f7306c3282d3ab8669900316ffe", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试:证明 Responses 输入 namespace 策略——只有普通原生(非 compact、非 OAuth、非 legacy Cindy)账号保留 standalone external_input 的 namespace;stripOpenAIResponsesInputNamespaces 仅剥离带 call_id 关联/无名条目的 namespace 且幂等;Forward(native/passthrough 两态)把带 namespace 与大整数扩展字段的 standalone 输出原样送上游。主题为核心 Responses 协议保真机制。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream file. Anchors: TestOpenAIResponsesStandaloneOutputNamespacePolicy L13-33 (ordinary_native=true; compact/oauth/legacy_cindy/no_account=false); TestOpenAIResponsesNamedOutputNamespacesKeepOnlyStandaloneIdentity L35-62 (indices 0-2 kept verbatim, 3-5 stripped, idempotent, legacy mode strips all); TestOpenAIGatewayForwardPreservesNamedStandaloneOutputNamespaces L64-91 (JSONEq on forwarded input incl. 9007199254740993 raw).", - "Subjects shouldKeepOpenAIResponsesStandaloneOutputNamespaces / stripOpenAIResponsesInputNamespaces are core forwarding normalization; shared fixtures come from the rejected-field test harness.", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_namespace_roundtrip_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "aed3443765a054aa5105be7cdb14d84e9ad0c071a229c5bf42c99c92edc8a7f3", - "review_fingerprint": "aed3443765a054aa5105be7cdb14d84e9ad0c071a229c5bf42c99c92edc8a7f3", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试:用自定义 upstream stub 模拟「function_call 必须回传 namespace」的上游,证明两轮 Forward(native/passthrough × 有无 tools/null namespace)把首轮输出的 namespace 原样回传、每轮一次成功不触发重试;以及 rejected-field 兼容路径对 Unknown parameter 'input[1].namespace' 剥离后重试但对 Missing namespace 不删除字段。主题为核心 Responses 转发保真与拒字段重试机制。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream file. Anchors: namespaceRoundtripUpstream.Do L24-52 (400 when namespace missing on round-trip); TestOpenAIResponsesNamespaceRoundtripPreservesModelHistory L58-105 (JSONEq of full second-turn input, bodies len 2, first-attempt success); TestOpenAIResponsesNamespaceRejectionCompatibilityRemainsExact L107-123 (strip-on-unknown keeps null namespace + encrypted_content; normalizeOpenAIResponsesRejectedFieldRetryBody returns changed=false for Missing).", - "Subjects: OpenAIGatewayService.Forward round-trip fidelity and normalizeOpenAIResponsesRejectedFieldRetryBody (core).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_native_fidelity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1a09fbd278289118c14af5b197589673103490bde26b52fe83cf54ccbf64b6bc", - "review_fingerprint": "1a09fbd278289118c14af5b197589673103490bde26b52fe83cf54ccbf64b6bc", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增 unit 标签测试:证明兼容 base_url 账号的原生 Responses 转发保真——reasoning/item_reference/compaction/encrypted_content/未知扩展字段与 previous_response_id、store=false 全部原样上送且调用方 payload 不被改写(即使先写入 invalid-encrypted-content lineage 标记也不删历史);effort 与 wire 一致(显式值/别名物化/自定义名不猜测);chat 路径先物化别名再做模型归一(native chat 用 reasoning_effort、responses 用 reasoning.effort)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream file, //go:build unit. Anchors: TestNativeResponsesFidelityPreservesCompatibleState L20-64 (passthrough x wsEnabled matrix, JSONEq input/reasoning, canonical payload immutable, lineage marker via test-only wrapper does not authorize deletion); TestNativeResponsesFidelityEffortMatchesWire L67-117; TestNativeChatReasoningAliasIsMaterializedBeforeModelNormalization L119-152.", - "Depends on the unit-tagged wrapper markOpenAIWSInvalidEncryptedContentLineage from openai_lineage_regression_helpers_test.go (see that entry's finding about the production path having moved on).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_oauth_429_classifier.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2cb5d5d637bf9119f7d37bb9e487d173edf8b2c52cd9bbbc12028c27b54539e0", - "review_fingerprint": "2cb5d5d637bf9119f7d37bb9e487d173edf8b2c52cd9bbbc12028c27b54539e0", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_oauth_429_classifier_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cba4c18839743c67ddddf0d28d49f60e5f7c74def51dd351350da1d7685c7bf4", - "review_fingerprint": "cba4c18839743c67ddddf0d28d49f60e5f7c74def51dd351350da1d7685c7bf4", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增 unit 标签测试:证明 429 分类器四条边界——未用尽窗口的事故性 429 判 transient 不产生长冷却;两窗口同时用尽取更晚 reset 且 Window=multiple;结构化硬配额码跨 HTTP JSON/SSE response.failed/WS error 三种载荷生效且缺 reset 证据时不虚构截止时间;错误 message 文本不能把 transient code 升级成配额。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Anchors: TestClassifyOpenAIOAuth429_IncidentTransientHeadersDoNotCreateLongCooldown L13-27; _ExhaustedWindowsUseLaterReset L29-45; _StructuredHardCodesAcrossTransports L47-73 (wantReset nil means no invented deadline); _MessageTextCannotUpgradeTransientCode L75-83.", - "Subject classifyOpenAIOAuth429At is core (openai_oauth_429_classifier.go).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_oauth_passthrough_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a76461b910a9ca7161083fc57892f6744c40320a9a8d9542e4ef5d78eda30ffe", - "review_fingerprint": "a76461b910a9ca7161083fc57892f6744c40320a9a8d9542e4ef5d78eda30ffe", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI OAuth/APIKey passthrough 转发的大型单测(3322 行,全文已读):断言仅替换认证的透传语义(namespace/tool_choice 保留、敏感入站头剥离、Codex 出站身份统一含复合 UA 与 originator 配套 #3901)、compact JSON 语义、错误净化重建不泄漏上游域名/密钥、Retry-After 严格校验、指纹 ID 头/体一致性、codex_cli_only 门。下游相对上游新增:request-integrity observe 模式、HTTP previous_response_id 端点契约(OAuth 拒发、APIKey 原样保真)、invalid_encrypted_content 终态不重放不改状态不落账号副作用、continuation 错误先于账号副作用终止、compact 错误延迟渲染交 handler、流缺终态事件改为硬错误、瞬时 5xx 表与 OAuth 429/529 语义、Cindy 余额 repo 桩。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f (+675): +TestOpenAIGatewayService_OAuthResponsesRequestIntegrityObserve, +_HTTPPreviousResponseUsesEndpointContractIndependentOfWSConfig, +_OpenAIPassthrough_InvalidEncryptedContentTerminatesWithoutMutatingState / _ResponseFailedInvalidEncryptedContentTerminatesWithoutReplay / _InvalidEncryptedContentFirstErrorStopsAdditionalResponses / _ContinuationErrorsStopBeforeAccountSideEffects, compact keepalive tests renamed to DefersRendering/DefersTerminalRendering, InfoWhenStreamEndsWithoutDone -> MissingAuthoritativeTerminal (hard error 'stream usage incomplete: missing terminal event'), cindy-balance methods on openAIPassthroughFailoverRepo stub.", - "Key proven invariants: upstream.bodies length 1 on continuation/state errors (no replay of encrypted history), c.Writer not written before failover, ops events carry Passthrough+Kind, sanitized bodies never contain secret-upstream.example / sk-upstream-secret.", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_oauth_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e8b34a3e7e1a8243cec7026008465dabf18194ab1de4fe4b87ff9ead2ec007ff", - "review_fingerprint": "e8b34a3e7e1a8243cec7026008465dabf18194ab1de4fe4b87ff9ead2ec007ff", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "OpenAI OAuth 登录/换码/刷新与凭据构建:PKCE 会话、state 常量时间比较、ID token 解析、accounts/check 补全 plan_type/订阅到期(含 workspace 与个人订阅区分、poid 匹配)、best-effort 关闭训练共享、PAT 校验。下游相对上游仅改刷新链路:RefreshAccountToken 先解析账号级 Codex 出站身份(resolveCodexOutboundIdentityForAccountContext),实现 OpenAIOAuthIdentityRefresher 的客户端用该 UA/originator 刷新(与推理同一身份,配合下游 Codex 探测加固),身份为空或客户端不支持时回退原 RefreshTokenWithClientID。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: +refreshTokenWithIdentity L219-236 (OpenAIOAuthIdentityRefresher type-assert, UA+originator both required, else fallback); RefreshAccountToken tail now resolves account identity and calls it (L430-435); RefreshTokenWithClientID delegates with empty identity.", - "Rest of file (enrichTokenInfo workspace/personal subscription disambiguation, BuildAccountCredentials refresh-token-empty guard) matches upstream v0.2.7 content per diff.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_official_http_failover.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "c61d339b8b4ca5f21a88cf7a5cec4e4ea4e2801b89f30f00d54f872b1fd9c534", - "review_fingerprint": "c61d339b8b4ca5f21a88cf7a5cec4e4ea4e2801b89f30f00d54f872b1fd9c534", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "整文件下游新增:官方直连 OpenAI APIKey HTTP 处理链的 failover/状态策略开关。context 标记 + 每个使用点重复身份校验(仅 PlatformOpenAI+APIKey,排除 Cindy profile/legacy Laxa/OAuth,共享 handler 无法改变 Cindy 或 OAuth 行为);成功时上报健康、清 429 重试窗、重置该账号该模型的瞬态失败连击;失败时经 ObserveOpenAIOfficialHTTPAccountHealthFailure 计入 APIKey 健康熔断(SuppressAccountHealthPenalty 与取消场景豁免);pool 重试策略在标记面内恢复上游的 transient-processing 例外。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream. Anchors: IsOpenAIOfficialHTTPFailover L20-30 (marker + identity gate); ReportOpenAIOfficialHTTPAccountScheduleResult L43-74 (health success observe, openaiOAuth429RetryStartedAt.Delete, recordOfficialSuccess under account lock, scheduler.ReportResult); ObserveOpenAIOfficialHTTPAccountHealthFailure L78-90 (context.WithoutCancel); openAIHTTPPoolRetryable L94-100.", - "Deliberately does not touch OAuth/Cindy probe leases (comment L40-41); exported ResolveOpenAIAccountUpstreamModelForRequest is a read-only projection for handler reporting.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_official_http_failover_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0e6fae08ddbcbffa1ba2fa08ba6f1746bcdf5fc66d4cf4b475e051b832b304b0", - "review_fingerprint": "0e6fae08ddbcbffa1ba2fa08ba6f1746bcdf5fc66d4cf4b475e051b832b304b0", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试:证明官方 HTTP failover 门需要 context 标记加普通 APIKey 身份(canonical Cindy、legacy Laxa base_url、Cindy profile、OAuth、非 OpenAI 平台全部拒绝);成功只重置该账号该模型的瞬态连击(其他模型/账号的连击与冷却保留,连击梯度 0/10s/45s);健康失败只计一次且仅在熔断触发时落库/写缓存/加运行时阻塞(enabled/threshold 矩阵)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Anchors: TestOpenAIOfficialHTTPFailoverRequiresMarkerAndOrdinaryAPIKeyIdentity L15-40 (10-case table); TestOpenAIOfficialHTTPSuccessResetsOnlyTheSuccessfulModelStreak L42-93; TestOpenAIOfficialHTTPHealthFailureCountsOnceAndPersistsOnlyOnTrip L95-144 (recordCalls==1 guards double counting through old and official reporters).", - "Subjects are the new official-HTTP failover surface plus openAIAccountModelTransientState and RateLimitService health breaker (core).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_official_http_state_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "465cbabe986703ec21876664be98b9f56eabd4899b07dee1091b1462a6e947b1", - "review_fingerprint": "465cbabe986703ec21876664be98b9f56eabd4899b07dee1091b1462a6e947b1", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增 unit 标签测试:证明官方 HTTP 面的状态语义——传输错误分级(瞬时 H2 只 failover;持久代理错误加 10 分钟 temp unschedulable + 运行时阻塞;客户端取消与插件已发送为终态直传);503 连击只落模型级瞬态冷却(0/10s/45s)不加账号级惩罚;pool 模式 401 不适用显式 temp 规则而 403/429 可按规则落模型冷却,重试耗尽不加账号级冷却;transient-processing 400 与 server_is_overloaded 503 保持同账号可重试且不被 request-rejection 分类吞掉。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Anchors: TestOpenAIOfficialHTTPTransportState L18-60 (PluginTransportError RequestSent terminal); TestOpenAIOfficialHTTP503StreakHasNoExhaustionPenalty L62-87; TestOpenAIOfficialHTTPPoolAuthQuotaRules L89-123 (wantRule excludes 401); TestOpenAIOfficialHTTPPipelineRetryMarkers L125-150 (openAIHTTPPoolRetryable unmarked path unchanged, shouldDisable precedence).", - "Subjects: handleOpenAIUpstreamTransportError, CooldownOpenAIRetryExhausted, handleOpenAIAccountUpstreamError, failoverOpenAIUpstreamHTTPError - all core failover surfaces.", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_ollama_continuation_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c02dda452814091f47bcd2495d541f59a9f614534315044b2cfdf1e81f5b32b8", - "review_fingerprint": "c02dda452814091f47bcd2495d541f59a9f614534315044b2cfdf1e81f5b32b8", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增 unit 标签小测试(43 行):证明发往 ollama.com /v1/responses 的转发把 max_output_tokens 钳到 65535 的同时不破坏各平台的 continuation 策略——OpenAI 平台账号保留 previous_response_id 原生引用,Deepseek 平台账号走既有无状态适配(剥离该字段),模型名不变。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Anchors: TestForwardResponsesOllamaClampPreservesContinuationPolicy L17-43: table {openai_native_reference keeps resp_native_reference, existing_cn_stateless_adapter strips}; asserts URL https://ollama.com/v1/responses and clamped 65535.", - "Subject is core Forward + ollama clamp normalization; fixtures ollamaUpstreamTestAccount/rawChatCompletionsTestConfig are shared test helpers.", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_passthrough_normalization_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9c52daafbf732ad1b2bbd022da7e8a6f593325a7025bb2a4afce2764f12a18d2", - "review_fingerprint": "9c52daafbf732ad1b2bbd022da7e8a6f593325a7025bb2a4afce2764f12a18d2", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "透传体归一化单测:断言 OAuth 透传剥离 ChatGPT 内部不支持字段、prompt->input 兼容包装、字符串/对象 input 包成数组、WS 兼容体仅对 OAuth/SetupToken 改写(APIKey/Cindy 原样)、原生 item ID 前缀清洗(call_id 保留)、工具/JSON schema 净化。下游相对上游改动集中在 GPT-6 Astra 的 reasoning.mode 语义:Astra 目标保留官方 mode/effort 原样(pro 不再映射 max、缺 effort 不补),并新增按解析后目标模型判定的 ForModel 变体(公共别名映射到 Astra 时同样保留,映射到非 Astra 时沿用旧 strip/pro->max),调用方字节不被改写。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: TestNormalizeOpenAIResponsesReasoningMode -> ...ForModel_UsesResolvedTarget (L169-199, resolved target decides, caller bytes immutable); +TestNormalizeOpenAICompatibilityBodiesForModel_PreserveMappedAstraMode (L201-226, account-type x target matrix); renamed _AppliesOfficialReasoningMode; Astra preservation tests L124-167 and L228-249.", - "Subjects normalizeOpenAIPassthroughOAuthBody(ForModel)/normalizeOpenAIResponsesWebSocketCompatibilityBody(ForModel)/normalizeOpenAIResponsesReasoningMode(ForModel)/normalizeOpenAIResponseFormatSchemasBody are core protocol normalizers.", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_plugin_transport.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "660c449e1b80f96fb1bf300e969056fc8791c5713c8faa9dd3c5f3eb0b3a1c19", - "review_fingerprint": "660c449e1b80f96fb1bf300e969056fc8791c5713c8faa9dd3c5f3eb0b3a1c19", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "宿主到插件的 OpenAI OAuth 传输桥:doOpenAIUpstream 在 PluginManager.RoundTripOpenAIOAuth 命中(能力绑定启用)时把真实请求交给插件运行时,未命中回落 HTTPUpstream;账号测试路径 doOpenAIAccountTestUpstream 同理。下游相对上游新增 codexWireObserver context 钩子(观测最终 wire 请求)并让账号测试未命中插件时经 prepareCodexTransport 走与真实转发相同的 zstd 压缩边界(插件有意拿明文,压缩只做在经 HTTPUpstream 发出的副本上)。桥不含业务规则,OAuth wire 归 codex-runtime 插件。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: +withCodexWireObserver/codexWireObserverFromContext L8-23; account-test path now builds wire via prepareCodexTransport and sends wire not request (L57-76).", - "Call chain: PluginManager.RoundTripOpenAIOAuth (plugin_manager.go L1251) routes to plugin runtime with availability/exit handling; parity with doOpenAICodexUpstream (openai_codex_request_compression.go L128) per comment.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_previous_response_id.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3183779b11dce2be331dfccbadadca232c54b195ebd7b59381fd634b31776873", - "review_fingerprint": "3183779b11dce2be331dfccbadadca232c54b195ebd7b59381fd634b31776873", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "previous_response_id 的分类与校验:resp_*/msg_*/未知三分类用于诊断。下游相对上游新增 ParseOpenAIContinuationAnchor:缺失/null/空白视为无锚点,其余必须是 JSON 字符串且匹配 resp_* 且长度不超过 1024(OpenAIContinuationAnchorMaxLength),否则返回统一的 ErrInvalidOpenAIContinuationAnchor;分类里响应 ID 匹配也加了同一长度上界,防上游不可控超长串进正则。宿主续写协议校验机制。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f (+46/-7): +OpenAIContinuationAnchorValidationMessage/MaxLength + ErrInvalidOpenAIContinuationAnchor L16-20; length bound in ClassifyOpenAIPreviousResponseIDKind L33; +ParseOpenAIContinuationAnchor L50-72 (typed json.RawMessage check, null tolerated, non-string rejected).", - "Consumers: continuation contract tests in openai_oauth_passthrough_test.go (OAuth HTTP rejects before send with previous_response_id message) and previous_response_id_test.go.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_previous_response_id_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5a616e9d44ee2ca33689e6b7e76412103a1b267c1afc947b3686303b5f118a30", - "review_fingerprint": "5a616e9d44ee2ca33689e6b7e76412103a1b267c1afc947b3686303b5f118a30", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "previous_response_id 校验单测:分类三态与 message-id 识别为上游既有;下游新增 ParseOpenAIContinuationAnchor 的 15 例表——缺失/null/空串/空白为无锚点,合法 resp_* 含生产长度(452 字符)与 trim,超 1024 上界、数字/布尔/对象/数组、msg_*/other_*/裸 resp_ 全部返回 ErrInvalidOpenAIContinuationAnchor,证明的是下游续写锚点强校验。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f (+51): TestParseOpenAIContinuationAnchor L40-83 with productionLengthID and overLimitID constructions; errors.Is against the sentinel.", - "Subject ParseOpenAIContinuationAnchor is core continuation validation (openai_previous_response_id.go L50-72).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_profit_control.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9147c345758942843f584500b63fdd37357c275fd2bae85ad7af9d5753b4afb5", - "review_fingerprint": "9147c345758942843f584500b63fdd37357c275fd2bae85ad7af9d5753b4afb5", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 请求/turn 定价上下文与利润门构造;新增固定 false 常量、只清门 helper;request/turn/resolve 的 canonical 边界在读历史分组前返回;turn 仍先写 pricingAt。;既有阈值公式、raw veto、终态账号刷新、门回传与 sticky helpers 未改。", - "evidence": [ - "Full source/diff review and exact test selectors: artifacts/evidence/v027-astra-dormant-profit-review.json", - "Canonical request/turn/gateway boundaries remain dormant; old columns, saved multipliers, pricingAt and private arithmetic are retained. No model requests or live data reads." - ] - }, - { - "path": "backend/internal/service/openai_profit_control_legacy_diagnostics_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ff23a1228b561c640bdc28b1b7dc2d2cd0bb7ee0a9b5b2bcb82fc958aa799eb6", - "review_fingerprint": "ff23a1228b561c640bdc28b1b7dc2d2cd0bb7ee0a9b5b2bcb82fc958aa799eb6", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "无利润耗尽原因,但模型不匹配与 compact sentinel 仍给出原有普通诊断;有效账号即使价格昂贵仍能被选。", - "evidence": [ - "Full source/diff review and exact test selectors: artifacts/evidence/v027-astra-dormant-profit-review.json", - "Canonical request/turn/gateway boundaries remain dormant; old columns, saved multipliers, pricingAt and private arithmetic are retained. No model requests or live data reads." - ] - }, - { - "path": "backend/internal/service/openai_profit_control_paths_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b678e58411f8524def4a9d3fa1e5fa0ab36260aef7539763021283037a65e947", - "review_fingerprint": "b678e58411f8524def4a9d3fa1e5fa0ab36260aef7539763021283037a65e947", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "previous-response binding、legacy selector、真实显式排除、倍率变化、用户 override、composite 两侧分组倍率和 eager sticky 均保留原有非利润语义。", - "evidence": [ - "Full source/diff review and exact test selectors: artifacts/evidence/v027-astra-dormant-profit-review.json", - "Canonical request/turn/gateway boundaries remain dormant; old columns, saved multipliers, pricingAt and private arithmetic are retained. No model requests or live data reads." - ] - }, - { - "path": "backend/internal/service/openai_profit_control_pricing_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "dcef2499a1cda59fbd373d0dddd1e7f8468e6888d379308338ea3837c7d355cc", - "review_fingerprint": "dcef2499a1cda59fbd373d0dddd1e7f8468e6888d379308338ea3837c7d355cc", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "request/turn/failover 的 pricingAt,peak 与普通价格倍率,Responses 能力选择保持;利润配置不再把账户倍率分成准入/拒绝。", - "evidence": [ - "Full source/diff review and exact test selectors: artifacts/evidence/v027-astra-dormant-profit-review.json", - "Canonical request/turn/gateway boundaries remain dormant; old columns, saved multipliers, pricingAt and private arithmetic are retained. No model requests or live data reads." - ] - }, - { - "path": "backend/internal/service/openai_profit_control_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "01ed6e67de7a9c07c5d48617644d4d853824e770b5a3b6be32d0872cd6a73685", - "review_fingerprint": "01ed6e67de7a9c07c5d48617644d4d853824e770b5a3b6be32d0872cd6a73685", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "enabled/disabled/多平台历史值均不能建门;昂贵与缺倍率账号仍可被选,显式排除仍导致正常耗尽。", - "evidence": [ - "Full source/diff review and exact test selectors: artifacts/evidence/v027-astra-dormant-profit-review.json", - "Canonical request/turn/gateway boundaries remain dormant; old columns, saved multipliers, pricingAt and private arithmetic are retained. No model requests or live data reads." - ] - }, - { - "path": "backend/internal/service/openai_quota_auto_reset.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5ff709a91bdac0adbf32093b7c59b2c4bac8efc63982411c5ac895caa94692da", - "review_fingerprint": "5ff709a91bdac0adbf32093b7c59b2c4bac8efc63982411c5ac895caa94692da", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI OAuth 账号重置卡自动消费服务:去重队列 + 分钟扫描补偿 + leader 锁削重 + PostgreSQL 幂等记录串行消费;状态机 checking/available/resetting/success/no_credit/failed 持久化在账号 Extra(只存不可逆指纹 AttemptCycleHash/AttemptCreditHash,防重启后换卡,不落卡 ID);候选按到期时间稳定排序、同周期只认原卡。下游相对上游仅一处收敛:buildOpenAIAutoResetUsageUpdates 改为复用共享的 buildCodexRateLimitExtraUpdates,删除内联 snapshot 构造(去重,无行为差异声明以静态阅读为限)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f is confined to buildOpenAIAutoResetUsageUpdates (L563-568): -22 inline snapshot lines, +1 call to buildCodexRateLimitExtraUpdates(usage.RateLimit, now).", - "Mechanism anchors (upstream-covered but read in full): Notify dedup + queue-full drop L157-172; idempotent consume with stable key oarc::: L376-419; selectOpenAIAutoResetCandidate refuses credit switching within a cycle L580-611; failState/persistState via accountRepo.UpdateExtra.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_quota_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5d4b5927078ee042c414683604ce911b96695235f2fbe21817b0ae1fe3925600", - "review_fingerprint": "5d4b5927078ee042c414683604ce911b96695235f2fbe21817b0ae1fe3925600", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "ChatGPT/Codex 配额查询与重置卡消费服务:/wham/usage 查询、reset-credit 明细、targeted/普通消费、spark shadow 防护(fail-closed 拒绝 shadow 重置)、agent-identity 断言头与任务恢复、错误体脱敏。下游相对上游改两处:QueryUsage 外挂 QuotaActivityService 度量(beginQuotaMeasurement/finishQuotaMeasurement);buildCodexSparkWindowExtraUpdates 收敛为直接调用共享 buildCodexRateLimitExtraUpdates(删除 60 行内联 Normalize 逻辑)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: +activity field L127, measurement hooks in QueryUsage (L151, L219); buildCodexSparkWindowExtraUpdates rewritten to delegate for codex_bengalfox (L611-622).", - "Full read confirms shadow guard ordering (resetCredit loads account before prepareUpstreamCall, ErrSparkShadowResetNotSupported 409), sanitized OpenAIRateLimitResetCreditDetail keeps no upstream ids, mapUpstreamStatus collapses 4xx to 502 except 401/403/429.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_raw_stream_truncation.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f13e00756fdd4ab1abea24562ecac836929b1cd3249d30ab64f2591bb1f173b6", - "review_fingerprint": "f13e00756fdd4ab1abea24562ecac836929b1cd3249d30ab64f2591bb1f173b6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "raw Chat Completions 直转流的截断判定与 ops 记录(修复 HTTP 200 假成功)。下游相对上游收紧终止语义:不再把 [DONE]/usage 当终止信号,只有每个观察到的 choice 都给出 finish_reason 才算语义完成;并新增 function 工具调用完整性校验(id/name 齐全、拼接后的 arguments 是合法 JSON,finish_reason=tool_calls 但没见过工具增量也算无效),违规产生 upstream_invalid_tool_call 协议失败;非 SSE 体现在也按未终止处理。未写出字节时构造可换号的 502 failover。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f (+96/-42): choices/tools/toolChoices maps + openAIRawFunctionArguments (L28-44); per-choice finish_reason tracking and tool-call validation in ObserveDataLine (L60-115); Terminated requires err==nil && all choices finished (L118-120); IsTruncated now ignores its bool arg and treats non-SSE bodies as incomplete (L124-126, was previously exempt).", - "Maps are request-scoped, keyed by upstream choice/tool indexes (bounded by stream lifetime); error body classification stays aligned with classifyOpenAIUpstreamStreamReadError (L196-210).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_configuration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a70d3501780c3ab418cc9b25792e28a8da371649535796ca57bf6eeb8862e390", - "review_fingerprint": "a70d3501780c3ab418cc9b25792e28a8da371649535796ca57bf6eeb8862e390", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(上游无此文件),验证下游扩展的 reasoning 配置对象(mode/context/future 等字段)的归一化契约:normalizeOpenAIPassthroughOAuthBody 对官方 OAuth 上游剥离下游专有 mode(pro→effort max,gpt-6-astra 保留原样),WS 兼容体对 APIKey 账户透传、对 OAuth/SetupToken 官方化;还断言大整数/高精度小数不被 float 归一化破坏、reasoning 在相邻适配器(图片工具剥离、空 base64 清洗)后逐字段保留、OpenAIResponsesRequireNativeUpstream 的判定表以及 imageBridgeControls 对 json.Number 计数的兼容。被测函数均为宿主协议机制。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: TestOpenAIReasoningConfigurationNormalization L11-L47 (per-model official vs raw expectations incl. account-type matrix), RequiresNative table L69-L87, WS compare number preservation L89-L115 (9007199254740992 vs ...93 must differ), adjacent-adapter survival L117-L134, Cindy count number compat L136-L149.", - "Subjects live in core: openai_gateway_request_body.go (normalize* L1295/L1434), openai_request_capabilities.go (OpenAIResponsesRequireNativeUpstream L12), openai_ws_forwarder_payload.go (L369/L481/L501), plugin_image_bridge.go (imageBridgeControls L23) - protocol/glue, no plugin business rule re-implemented in the test.", - "git ls-tree aea725f -- is empty: whole file is downstream delta.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_effort_candidates_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "520c32eee33c16cda60e07de2dbaee099a62b2a957b04ed4e9368aad410696ec", - "review_fingerprint": "520c32eee33c16cda60e07de2dbaee099a62b2a957b04ed4e9368aad410696ec", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "上游已有文件,下游 diff 重写断言以证明修复:请求体未显式发送 effort 时不再从原始模型后缀猜测记账元数据(xhigh/max 期望改为 nil),显式 max 不再被非 5.6 首候选折叠成 xhigh;回归测试新增关键断言——后缀模型 gpt-5.3-codex-xhigh 经 Forward 后 reasoning.effort=xhigh 必须真实出现在上游 wire body(模型剥后缀为 gpt-5.3-codex),result.ReasoningEffort 按实际请求记录。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: diff vs aea725f rewrites 4 table expectations (L27-L56) and TestExtractOpenAIReasoningEffortModelCandidates now requires Nil (L72-L78); TestOpenAIGatewayServiceForwardOAuthDerivesEffortFromSuffixModel adds require reasoning.effort==xhigh on upstream.lastBody (L117).", - "Proves the materializeOpenAIForwardReasoningEffort fix in openai_reasoning_effort_policy.go L465-L475: alias effort is materialized onto the wire instead of inferred for metadata only.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_effort_policy.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e07917435e296fe64e73650b3d728cb409f2d783b08e5d7a2eb0f37ea81e160a", - "review_fingerprint": "e07917435e296fe64e73650b3d728cb409f2d783b08e5d7a2eb0f37ea81e160a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "分组 reasoning-effort 策略(上限/deny/按模型映射)本体是上游 v0.2.7 内容;下游 diff 修复别名后缀链路:新增 materializeOpenAIForwardReasoningEffort(账号选定后把模型后缀 effort 物化进 wire body,并对该新值恰好套用一次已绑定策略,显式字段不二次映射),applyOpenAIWSReasoningEffortPolicy 与 ApplyOpenAIReasoningEffortPolicy 现在先物化别名 effort 再执行策略,使后缀派生的 effort 同样受组策略约束并真实发往上游。策略为宿主通用机制,model-policy 插件中无重复实现。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: diff vs aea725f adds materializeOpenAIForwardReasoningEffort L465-L475, rewrites applyOpenAIWSReasoningEffortPolicy L570-L586 and ApplyOpenAIReasoningEffortPolicy L588-L599 to call materializeOpenAIModelReasoningEffort (openai_codex_transform.go L680) first.", - "Callers traced: openai_gateway_forward.go L69/L77, openai_gateway_chat_completions.go L102, openai_gateway_chat_completions_raw.go L67, openai_gateway_passthrough.go L189 - all core forwarding paths; policy context binding via WithOpenAIReasoningEffortPolicy copies mappings (L436-L446) against later slice mutation.", - "rg -i reasoning.?effort over plugins/model-policy returned nothing: no second executor of this rule in a plugin.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_recovery.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ba069dac7fde6c786c95ef95222fdfc17faa02a46f0ff4f45b7fdb189c9fec18", - "review_fingerprint": "ba069dac7fde6c786c95ef95222fdfc17faa02a46f0ff4f45b7fdb189c9fec18", - "review_status": "pending" - }, - { - "path": "backend/internal/service/openai_reasoning_recovery_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a3687e311cfc013ed7987d0faeb278e5d41cb5c2324c76050b6dcf5760bf5dd1", - "review_fingerprint": "a3687e311cfc013ed7987d0faeb278e5d41cb5c2324c76050b6dcf5760bf5dd1", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试,跨 5 种终端处理模式(native/native_async/passthrough/buffered/passthrough_buffered)与 response.failed/response.done 两种终止事件证明:签名拒绝产生纯信号错误后 TryRecoverError 恢复成功,且早期 in_progress 事件的 usage(input_tokens=3) 作为证据写入 reasoning_recovery 运维事件(缺失 output_tokens 保持 unavailable 而非补零);Chat 回放场景中裸 SSE error 必须等到权威 failed 终端才重试并写入拒绝缓存,completed 终端出现则不重试不记忆;客户端部分写入后不可恢复。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: assertReasoningRecoveryUsageEvidence L20-L40 (usage_status available, missing output must not exist), TestOpenAIReasoningRecoveryLegacyDoneAndEarlierUsage L42-L58, TestOpenAIChatReasoningReplayWaitsForAuthoritativeRejection L60-L106 (completed => 2 requests + empty rejected cache; failed/done/eof => 3 requests + 1 cache entry + no resp_rejected leak), reasoningPartialWriter blocks recovery L108-L128.", - "Subject is the core recovery engine in openai_reasoning_recovery.go plus chat replay glue; go:build unit tag, no plugin rule re-implemented.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_recovery_terminal_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ed609a2b9248c6a616472566062d5931373daea3e1d7072433cc62bfe00000c2", - "review_fingerprint": "ed609a2b9248c6a616472566062d5931373daea3e1d7072433cc62bfe00000c2", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试,覆盖恢复终态矩阵(passthrough×{http,stream,buffered_sse}×4 种行为):耗尽单次重试后返回 OpenAIReasoningRecoveryTerminalError 且不再 errors.As 成 UpstreamFailoverError(不回调度器、无第三次 POST)、真实 HTTP 状态与客户端语义分开保留、非密文字段逐路径与入站相等、诊断 Wire.BodySource=frozen_request 且 GetBody 恒为 nil;负缓存命中跳过不刷新拒绝时间戳;not_attempted 原因枚举齐全;诊断与错误串不泄露密文、私密错误详情与 token;枚举清洗把未知 disposition 归一为 unknown;FailureTerminalForwarded 区分中断流与已转发终端。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: TestOpenAIReasoningRecoveryTerminalsPreserveClassificationAndDiagnostic L60-L177 (classification request_validation vs thinking_signature_invalid, SuppressAccountHealthPenalty, empty rateLimit/overload repo calls, secret non-leak loop L169-L172), frozen diagnostic no-GetBody test L179-L203, not-attempted reasons matrix L205-L240, enum sanitization L242-L255, terminal delivery matrix L266-L305.", - "Proves StopError/terminal contracts of openai_reasoning_recovery.go L599-L724 and diagnostic shaping; subject entirely core protocol.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_recovery_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "83d41ea705588ad6c7d2d136ce5b1120f9942ae580dc01d2377672d5ec37d02b", - "review_fingerprint": "83d41ea705588ad6c7d2d136ce5b1120f9942ae580dc01d2377672d5ec37d02b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增单元测试:严格拒绝包络接受矩阵(仅两个精确 code、大小写敏感、param 须指向真实 reasoning 密文项、混有 compaction 密文时无 param 不恢复、previous_response_id 存在即不以本地密文自证、孤儿工具输出阻断),单请求只允许一次额外 POST;恢复只删 encrypted_content、其余字段字节保留并回调拒绝哈希;401/402/403/407/429 永不重试;重试保留调用方 deadline/取消并绑定身份(auth/endpoint/method/proxy/body 任一变化即报错);负记忆精确匹配、TTL 不滑动、缓存失败只降级;scope 因认证头或代理不同而隔离、reasoning 键序不影响语义身份。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: fixture L21, strict matrix 18 cases L43-L84, field preservation + rejected-hash callback L86-L114, protected statuses L137-L141, context/identity binding matrix L144-L195, negative memory non-sliding L231-L256, scope isolation L258-L276, single-retry Forward matrix independent of pool_mode_retry_count L278-L322, SSE/buffered failed-attempt usage L324-L365, committed SSE never replayed + FailureTerminalForwarded L367-L389.", - "Directly exercises openai_reasoning_recovery.go TryRecover/PrepareRequest/skipRejectedHistory and buildOpenAIReasoningScope; L258-L276 is what proves the account/tenant scoping requirement of this slice.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_state_cache.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "35fe244e32000d6d9fe8ee4991427cf7415e35814173dc2c5f0ce39c2cc51e21", - "review_fingerprint": "35fe244e32000d6d9fe8ee4991427cf7415e35814173dc2c5f0ce39c2cc51e21", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增:推理状态缓存的作用域与预算原语。BuildOpenAIReasoningCacheScope 拒绝匿名来源,把 UserID/APIKeyID/GroupID/AccountID/来源身份摘要/endpoint/model/全部 reasoning 子字段纳入 ScopeHash,TenantHash 仅 user+apikey 以独立限额;canonicalReasoningCacheJSON 拒绝重复键与超过 64 层嵌套并用 UseNumber 保精度;容量常量(批 256KiB/64 项、总 64MiB/8192 条、租户 8MiB、拒绝表 8MiB/32768 条、查询上限 64)由 repository/gateway_cache_reasoning_state.go 强制执行,缓存有界且按实际账号维度键控;每请求 100ms I/O 预算互斥共享、只计 I/O 时间。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: bounds constants L18-L30, digest-only scope build L40-L81, duplicate-key/depth rejection L99-L155, optional OpenAIReasoningStateStore interface L193-L200 (Get never refreshes rejection TTL per comment L198), per-request budget with get-or-create mutex L226-L242 and Do() charging only elapsed I/O under its own lock L244-L265.", - "Enforcement traced: backend/internal/repository/gateway_cache_reasoning_state.go L140-L168 consumes these limits; store obtained via cache type assertion L202-L208, absence degrades to nil store (feature off), never to alternate business behavior.", - "git ls-tree aea725f -- empty: new downstream file. Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_state_cache_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cdd4485462843d59610484423f613ac79ca99e381b8d2f302b567094f25a2ac1", - "review_fingerprint": "cdd4485462843d59610484423f613ac79ca99e381b8d2f302b567094f25a2ac1", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试,证明缓存作用域与预算契约:user/key/group/account/身份摘要/endpoint/model/reasoning.mode 乃至超出 float 精度的整数任一变化都改变 ScopeHash,仅 user/key 改变 TenantHash;reasoning 键序重排得到相同 scope;重复键、双文档、截断 JSON 与 UserID=0 均返回 ErrOpenAIReasoningCacheInput;预算:已取消 ctx 不执行回调、超时耗尽后续调用得 ErrOpenAIReasoningCacheBudget、失败调用只扣 I/O 时间(模拟生成间隔不计费)、8 个并发消费者拿到同一预算实例。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: TestOpenAIReasoningCacheScope dimension matrix incl. 9007199254740992/93 distinction L16-L71, budget cancel/exhaust L73-L91, IO-only charging L93-L107, concurrent same-instance L109-L119.", - "Proves BuildOpenAIReasoningCacheScope / canonicalReasoningCacheJSON / OpenAIReasoningCacheBudget in openai_reasoning_state_cache.go; supports the requirement that replay caches are keyed by the actual account scope.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_reasoning_summary_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f4671f396198a0136ca8a6cf954cfe2cf0e9401829bddb61715414c1c4f430ee", - "review_fingerprint": "f4671f396198a0136ca8a6cf954cfe2cf0e9401829bddb61715414c1c4f430ee", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试,固化 reasoning.summary 目的地契约:仅当 OpenAI APIKey 账户把请求发往兼容网关主机(pnnl 大小写/显式 443 与 example 网关)时 detailed/concise 才钳制为 auto,且逐字节只改这一处;OAuth/Cindy/官方主机/8443 端口/HTTP/compact 路径/passthrough 模式全部原样返回;omit 模式删除 summary(仅剩 summary 时连 reasoning 对象一并删除)但保留 effort/context/extension;普通与 passthrough 两种上游构建器都应用该归一化且 GetBody 快照与 wire body 一致。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: compatibleSummaryRequest fixture with precise_integer 9007199254740993 L18-L28, clamp/no-op matrix L34-L74, model coverage L76-L90, omit mode L92-L111, builder + snapshot equality L113-L185.", - "Subject normalizeOpenAICompatibleResponsesReasoningSummary lives in core openai_gateway_request_body.go with per-account override via openai_compat.ExtraKeyReasoningSummaryMode; reasoning-summary destination contract is core forwarding behavior, no plugin owns it.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "38f67146344a76d63a3d47370db8f24ee64b17740ed4fb528801f48fb3ab10cf", - "review_fingerprint": "38f67146344a76d63a3d47370db8f24ee64b17740ed4fb528801f48fb3ab10cf", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增:拒答恢复的核心原语。关键词匹配器做 NFKC、弯引号折叠、空白折叠、小写归一,只扫描前两个段落且不超过 2048 个字符,关键词最多 128 个、每个不超 64 字符,替换文不超 8KiB;设置校验(rewrite 需要关键词+替换文,cyber failover 与 cyber_session_block 互斥);两种换号 failover 错误统一 503、请求级、NextAccountRetry 且 SuppressAccountHealthPenalty,cyber 变体对客户端只暴露 upstream_retry_exhausted;早期流改写资格仅授予纯文本请求(递归检查 tools/tool_choice/modalities 与图像模型)。该规则来自系统设置,插件中无重复实现。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: limits L17-L23, default keywords L35-L40, NewOpenAIRefusalMatcher L71-L87, normalizeOpenAIRefusalText (NFKC + quote fold + space collapse) L162-L175, ValidateOpenAIRefusalRecoverySettings conflicts L113-L129, failover constructors L214-L241, early-stream eligibility L271-L344, cyber policy ops mark with usage L346-L361.", - "Runtime comes from SettingService.GetOpenAIRefusalRecoveryRuntime (setting_gateway_runtime.go L159/L213); rg over plugins/ shows no plugin implements refusal/cyber rules (only prompt text files and the unrelated codex-runtime ChatFields list mention the word) - no second executor.", - "git ls-tree aea725f -- empty: new downstream file. Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_json.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3af08886d2bf74b3df331088bfe92862b4748dee7ea439da6c145eec2cba9091", - "review_fingerprint": "3af08886d2bf74b3df331088bfe92862b4748dee7ea439da6c145eec2cba9091", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增:非流式 Responses JSON 的拒答改写。仅当 status=completed 且所有输出项为 reasoning 或只含 output_text/refusal 内容的 assistant message 时,把可见文本拼接后按前两段匹配;命中则以首条 message 的 ID 构造单条替换 message 覆盖 output,其余顶层字段(usage 等)经 RawMessage 原样保留。任何工具/图像/未知内容类型直接原样返回,不会伪造。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: envelope structs L8-L25, gate conditions L32-L44 (non message/assistant output => no-op), visible-text concat incl. refusal parts L48-L57, replacement output build preserving firstMessageID L72-L87, raw map re-marshal keeps unknown top-level fields L68-L92.", - "Called from stream state terminal handling (openai_refusal_recovery_stream.go L112/L226) and non-stream handlers in openai_gateway_response_handling.go / openai_gateway_passthrough.go (traced by rg).", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_pipeline_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "86faa2a4c48566cda61c95a8ac66c90b8b67f01aa65aef521006e072a95eecb5", - "review_fingerprint": "86faa2a4c48566cda61c95a8ac66c90b8b67f01aa65aef521006e072a95eecb5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增管线级测试(1054 行),静态阅读证明:非流式 passthrough/translated 与 SSE→JSON 场景改写拒答文本/结构化 refusal 时保留 response ID 与 usage;cyber_policy 错误在所有形态(HTTP 错误、SSE failed、JSON failed)都终止而不进入 failover(errors.As 为 false)、绝不伪造 response.completed、只写一次 response.failed 并保留 usage;开关关闭时原样透传;先重试后改写路径返回 refusal-recovery failover 且客户端零输出;早期替换在终端事件前经 Flush 先行送达(io.Pipe 同步验证);非早期空终端从 output_item.done 恢复 message(含 reasoning 前置场景);第二段拒答与早期改写失败仍收集终端 usage。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: rewrite+usage L89-L108/L150-L194, prompt-retry-then-substantive L110-L148, cyber terminal matrix L196-L388 (never response.completed, GetOpsCyberPolicy usage marks), streaming cyber before/after reasoning and after early refusal output L390-L600, cross-delta rewrite L602-L829, translated handlers L831-L952, flush-before-terminal with openAIRefusalFlushRecorder + io.Pipe L954-L1054.", - "Subjects are core response handlers (handleNonStreamingResponse(Passthrough), handleStreamingResponse(Passthrough), handleErrorResponse(Passthrough)) plus this cluster's state machines; runtime injected via settingService cache, no plugin involved.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_request.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "9112a4e73e5e6362aa311827185d4f226c9d68f1c955a8875aa53e98bf73abc4", - "review_fingerprint": "9112a4e73e5e6362aa311827185d4f226c9d68f1c955a8875aa53e98bf73abc4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增:拒答恢复的请求侧修复。续写请求中移除网关生成的占位 assistant 项(msg_refusal_recovery_ 前缀或文本等于当前替换文),并在续写 user 消息前恰好插入一条带固定标记的 developer 恢复指令;PrepareOpenAIRefusalPromptRetry 在首次上游拒答后做立即重试的同款注入,字符串 input 被转换为 [developer,user] 数组;两者都以标记检测保证幂等,终端占位无后续 user 时不改写。重试门由 rewrite+cyber 开关和每请求一次的 attempted 标志控制。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: instruction constant with marker L16-L22, PrepareOpenAIRefusalContinuationRequest gate on RewriteEnabled L35-L41, placeholder detection (ID prefix or replacement text) L156-L186, terminal-placeholder-without-user no-op L123-L134, idempotence via marker scan L227-L234, string-input conversion L72-L102, rebuild inserting exactly one developer item L236-L273, per-request retry gate L290-L302.", - "Marker text is a fixed core constant; no plugin supplies or duplicates this instruction (rg over plugins/).", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_request_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "508c9e7baa1319e1d587fb9c0f1deb5f5ee755680da3ab831db20ad55cb3639f", - "review_fingerprint": "508c9e7baa1319e1d587fb9c0f1deb5f5ee755680da3ab831db20ad55cb3639f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试,证明请求侧修复契约:生产替换文占位与 msg_refusal_recovery_ 前缀占位都被移除并在续写 user 前插入 developer 指令(顺序 user/developer/user);重复占位折叠为一条指令;普通历史逐字节不变;占位后无 user 消息不改写;PrepareOpenAIRefusalPromptRetry 幂等且把字符串 input 转成 [developer,user] 并保留 stream 字段;并断言指令文本包含不重复拒答、给出最接近的允许替代等关键句。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: production placeholder removal L13-L36, reserved prefix L38-L48, repeated placeholders collapse L50-L60, ordinary history untouched L62-L70, requires later user L72-L80, idempotent retry L82-L95, string input conversion L97-L108, instruction content assertions L110-L115.", - "Proves openai_refusal_recovery_request.go behavior; subject is core request-side mechanism.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_stream.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5b6f9780037f94cd6d34e1fec8782ee724d465a3af83b140033e26b3f46d17d2", - "review_fingerprint": "5b6f9780037f94cd6d34e1fec8782ee724d465a3af83b140033e26b3f46d17d2", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增:SSE 拒答改写状态机(hold/pass/replace-early/replace)。缓冲上限 1MiB、扫描窗口两段/2048 字符,超限即 fail-open 透传;任何工具/图像/搜索类事件或非 message/reasoning 输出项立即透传;早期替换合成 created/item_added/part_added/delta 前缀并在终端合成 done/part_done/item_done/completed(响应与消息 ID 前后必须一致,不一致返回错误而非伪造);空 output 终端可从缓存的 output_item.done message 恢复(reasoning 的 item_id 不会遮蔽 message ID);failed/incomplete/cancelled 一律透传。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: action enum + state L16-L45, reserveLine 1MiB fail-open L47-L57, observe dispatch incl. done-event prefix-extension rule L59-L130, metadata capture with message-id binding rules L132-L174, restoreCompletedMessageIntoEmptyOutput only when output==[] L176-L198, early prefix/terminal builders with id-continuity errors L307-L390, passthrough triggers L269-L285, scan window L246-L267.", - "Consumed by HTTP stream handlers (openai_gateway_response_handling.go / passthrough) and by the WS wrapper in openai_refusal_recovery_ws.go; replacement events carry the terminal's own usage, nothing invented.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_stream_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6889fb37910b780b73eec5040eefe79a82fe72388dbc2470795f43410e3f0889", - "review_fingerprint": "6889fb37910b780b73eec5040eefe79a82fe72388dbc2470795f43410e3f0889", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试,静态阅读证明状态机行为:缓冲超 1MiB 与扫描超 2048 字符 fail-open;关键词命中后遇工具/图像事件仍透传;跨换行、第二段命中、第三段不命中;结构化 refusal 事件参与匹配;早期替换先发 delta 前缀、终端补齐 usage;非早期空终端从 completed message 恢复(output_text 与 refusal 两种内容);reasoning 的 item_id 不遮蔽 message ID;ID 不匹配或终端 output 非空时保持终端权威(透传或报错,不伪造);sanitizeOpenAICyberPolicyFailedEvent 保留 id/model/output/usage、错误码换成 upstream_retry_exhausted 且不泄露 cyber/blocked 字样。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: buffer fail-open L12-L28, tool/image passthrough after match L30-L68, paragraph window behaviors L70-L153, structured refusal L155-L175, early emission + terminal completion with usage L177-L229, empty-terminal restore matrix L231-L320, reasoning id shadow test L322-L382, terminal-authority fallback L384-L439, cyber sanitize L441-L470, early-replacement validation errors L472-L527.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "36658b1bf1cd97b7833c1cb30458faeb7b205210381db4aaf0775e80b139c080", - "review_fingerprint": "36658b1bf1cd97b7833c1cb30458faeb7b205210381db4aaf0775e80b139c080", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增单元测试:默认关键词表 28 项;运行时加载只调一次批量 Get;匹配器对 NFKC/弯引号/多空格/大小写归一后命中并回报原始关键词;只扫前两段、第三段不命中、2048 字符上限;JSON 改写矩阵(纯文本与结构化 refusal 替换、第二段命中、工具/图像/incomplete 响应原样);cyber failover 错误契约(503、NextAccountRetry、不计健康惩罚、响应体只含 upstream_retry_exhausted 不含 cyber_policy);关键词归一去重与 64 字符上限;设置冲突校验。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: defaults L14-L20, runtime single GetMultiple L22-L34, normalized match L36-L43, early-eligibility table L45-L68, paragraph scans L70-L104, RewriteOpenAIResponsesJSON matrix L106-L185, cyber failover contract L187-L202, dedupe/limits L204-L252.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_ws.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a9faab11a5e0d5178c485b2ecc80fb6cd8ae180bf5155cbbe7f0c3d2c071e998", - "review_fingerprint": "a9faab11a5e0d5178c485b2ecc80fb6cd8ae180bf5155cbbe7f0c3d2c071e998", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增:WS 帧层拒答改写包装(实现 openai_ws_v2.FrameConn)。每轮次缓冲文本帧,总量超 1MiB 触发回调并 fail-open;复用 SSE 状态机(无早期发射模式),replace 时把合成 SSE 重新拆成 WS 文本帧发送并重置轮次;guardReplay 模式下非语义事件持续缓冲以保护回放安全判定;WriteRetryableFailure 丢弃本轮缓冲后发送净化的 response.failed(upstream_retry_exhausted,保留 id/output/usage);语义写入与任何下游写入分别跟踪,供回放安全决策使用;不可回放时降级为 WS 1013 关闭而非 failover。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: FrameConn wrapper L33-L50, Write dispatch with buffer cap + onBufferLimit L63-L139, per-turn reset on terminal L107-L123/L204-L214, writeDirect semantic tracking L141-L153, WriteRetryableFailure sanitization L188-L202, semantic-event classifier L221-L236, replay-safe error choice (failover vs WS close 1013) L238-L243, fixed retryable failure event L245-L247.", - "Buffered frames are bounded (1MiB per turn) and dropped on turn reset; consumed by openai_ws_forwarder_* and openai_ws_v2_passthrough_adapter (traced by rg).", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_refusal_recovery_ws_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3fed3fe0779a9484a4f8bc4e47d49890d5fe2344b57c5fef040e3899a6f44372", - "review_fingerprint": "3fed3fe0779a9484a4f8bc4e47d49890d5fe2344b57c5fef040e3899a6f44372", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试,证明 WS 包装行为:跨帧命中后整轮替换为 8 帧合成事件(created→completed,usage 保留),下一轮状态重置后正常帧即时透传;结构化 refusal 帧同样替换且输出不含 response.refusal;空终端从 output_item.done 恢复(含 reasoning 前置);第二段命中;超 1MiB 触发回调并 fail-open 只写原帧;replay-safe 时用 failover 错误、否则 WS 1013 关闭;WriteRetryableFailure 丢弃缓冲元数据只写净化 failed 事件(保留 id/output/usage,不含 cyber/blocked);缓冲元数据不算已写下游,首个语义事件先冲刷元数据再写。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: cross-frame rewrite + turn reset L15-L60, structured refusal L62-L92, empty-terminal restore L94-L158, second paragraph L160-L189, buffer fail-open L191-L206, replay-safe error selection L208-L220, retryable failure without buffered frames L222-L243, downstream/semantic tracking L245-L266, sanitize preserves usage L268-L286.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_request_capabilities.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "8bcfd992ecad0d2cfad9b09481c5d1ce5db112df40306be70214a64b4b9b2380", - "review_fingerprint": "8bcfd992ecad0d2cfad9b09481c5d1ce5db112df40306be70214a64b4b9b2380", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "整文件下游新增(29 行):OpenAIResponsesRequireNativeUpstream 判定 Responses 请求是否必须留在原生 Responses 上游、不得降级到 Chat-only 候选——previous_response_id/background/非 null conversation 直接要求原生,其余委托 apicompat 的 reasoning/input/tools 判定。调度候选过滤用,converter 侧独立再校验同一边界。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream (git ls-tree upstream prints nothing). Single exported function L12-29; delegates to apicompat.ResponsesReasoningRequiresNative/ResponsesInputRequiresNative/EffectiveResponsesTools+ResponsesToolsRequireNative.", - "Callers (rg): backend/internal/handler/openai_gateway_handler.go plus this file; unmarshal failure conservatively returns false (converter re-enforces).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_request_integrity.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "778410dcec574ce086ccbc4ed76ded921c51649989eb34a6ab7046e18cf1315b", - "review_fingerprint": "778410dcec574ce086ccbc4ed76ded921c51649989eb34a6ab7046e18cf1315b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "整文件下游新增:请求完整性守卫的模式解析与钩子骨架。模式 off/observe/enforce,仅对 OpenAI OAuth-like 账号生效,账号 Extra 显式值优先于全局配置;observe 只打差异标记 + 每账号 5 分钟限频告警(只记字段名,绝不落请求体/凭据);enforce 已接线但默认无人开启。快照按账号暂存于 gin context,换号 failover 前强制重置防止与旧快照比对;体超 4MiB 跳过;告警限频 map 上限 4096 并有过期驱逐与整表兜底。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream. Anchors: mode precedence requestIntegrityModeFor L98-110; stageRequestIntegrityOriginal resets slot first L133-148 (stale-snapshot defense); checkRequestIntegrity L211-245 (bytes.Equal fast path, 4MiB bound, field-names-only logging, enforce -> BadRequest OPENAI_REQUEST_INTEGRITY); requestIntegrityShouldLog bounded gate L252-274.", - "Design-attribution header comment L15-40 documents comparator shape borrowed from a third-party 0.2.4 distribution but implemented against sub2api helpers, and lists intentional v1 exclusions (compact, WS wire stage, CC//v1/messages bridges, account-test probes).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_request_integrity_semantics.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "752883614ce52cb9bbf7194671bc35de1908234c6d222ec1766b051f3e740044", - "review_fingerprint": "752883614ce52cb9bbf7194671bc35de1908234c6d222ec1766b051f3e740044", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "整文件下游新增:完整性比较器的语义层。requestIntegrityOptions 声明该路径应用过的服务侧改写(模型映射、Lite、namespace 摊平/剥离、图片工具策略、effort 策略回放),比较器在客户端体上回放同一批非有损转换后,仅比较 11 个语义键(model/input/instructions/reasoning/tools/tool_choice/...),首个差异按键名上报;有损转换(孤儿工具输出移除、无名工具丢弃等)刻意不被掩盖。含 CC 旧工具形态折叠、输入条目 replay 元数据剥离(id/call_id 归一)、instructions 前缀放宽、数值 1.0==1 归一。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "New downstream. Anchors: requestIntegrityComparedKeys L45-57; compareRequestIntegrity L68-114 (token-budget keys tolerated when absent on wire, DeepEqual per key); requestIntegrityRawCanonical L119-172 (original-only passes: effort policy, Lite, flatten/strip namespaces); canonicalizeRequestIntegrityInput L338-450 mirrors filterCodexInputWithOptions equivalences with NeedsToolContinuation-gated id preservation; relaxRequestIntegrityInstructions prefix acceptance L481-491; relaxRequestIntegrityTools image-bridge/strip tolerance L496-517.", - "This is a comparator, not a second forwarding pipeline (comment L181-184); it never writes to the wire body, so no duplicated-executor risk found.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_responses_ingress_compat.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "7dcacb2dcecbdc2c26cab8accc13c759efb053385ae0d49a832b170a18b85c29", - "review_fingerprint": "7dcacb2dcecbdc2c26cab8accc13c759efb053385ae0d49a832b170a18b85c29", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Chat 形态老客户端打 Responses 端点的入口归一化(messages/prompt/commands 别名转换)主体为上游内容;下游 diff 只有一处修复:messages 转成 input 时不再删除 previous_response_id——别名不是完整历史的证据,原生锚点保留给所选端点自行校验(与直接提供 input 的请求一致)。其余(工具/tool_choice 形态转换、prompt 字符串别名、模板与未知形态保留)与上游一致。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: diff vs aea725f removes only the `delete(request, \"previous_response_id\")` at the no-native-input branch and replaces it with the preserving comment (L53-L59); conversion pipeline via apicompat.ChatCompletionsToResponses L110-L154, top-level field application + legacy field cleanup L196-L224.", - "Caller chain: legacy ingress runs before endpoint selection in the gateway (traced by rg); a preserved anchor is later validated by the selected endpoint, e.g. the OAuth HTTP anchor rejection test in openai_responses_input_compat_test.go L346-L364.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_responses_ingress_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ff14fc88785dc741c60f94f977ad38b3b9ff499fa5f00c3d3a5daac64d8a5a46", - "review_fingerprint": "ff14fc88785dc741c60f94f977ad38b3b9ff499fa5f00c3d3a5daac64d8a5a46", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "上游已有测试;下游 diff 只改一条断言以证明修复:messages-only 请求转换后 previous_response_id 必须保留(原断言要求其不存在)。整体覆盖:tool_calls/tool 消息转 function_call(_output)、Chat 顶层字段转换(max_tokens→max_output_tokens 128、reasoning_effort→reasoning.effort+summary auto、工具与 tool_choice 摊平)、原生 input 优先且 messages 只被丢弃、prompt 字符串别名转 input、原生 prompt 模板与未知 prompt 形态原样保留、commands 一律删除。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: diff single assertion flip at L17 (resp_stale preserved); native-input authority test keeps tools untouched + resp_keep L48-L61, prompt template no-op L74-L83, unknown prompt shape L85-L94.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_responses_input_compat.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "2e2ae760bee42c895862d931f5b2e96be5c893d6249bb88d22df26f4cd044fec", - "review_fingerprint": "2e2ae760bee42c895862d931f5b2e96be5c893d6249bb88d22df26f4cd044fec", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "孤儿工具输出处理。下游相对上游:1) 清理逻辑重构为共享的 keep-mask(openAIResponsesOrphanToolOutputKeepMask),使解码请求适配器与 raw WS 透传共用同一份官方判定;2) 新增 validateOpenAIResponsesToolOutputs——推理签名恢复专用的只读校验,item_reference/带密文的 compaction 视为服务端持有上下文直接放行,孤儿输出返回 ContinuationStateUnavailable(400) 而不改写历史;3) truncateOpenAIResponsesInputText 与 openAIResponsesInputMayNeedTruncation 改为永远 false 的兼容壳——不再静默截断客户端/工具输出,超限交给上游报显式错误。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: keep-mask refactor L13-L85 (nil mask = unchanged), named standalone function output exemption L87-L91, read-only validate with server-context escapes L93-L143, truncation no-ops with rationale comments L145-L157.", - "validate is consumed only by openai_reasoning_recovery.go (openAIReasoningToolHistoryAllowsRecovery L391-L399) and plugin_codex_recovery selection query; the sanitize path stays the official ingress cleanup - the comment explicitly forbids the recovery check replacing it, so no duplicate executor.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_responses_input_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d3af980287948f19102e54141441b052ece11f222e34d8f63c65ccf4e3e3173e", - "review_fingerprint": "d3af980287948f19102e54141441b052ece11f222e34d8f63c65ccf4e3e3173e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "上游已有文件,下游大幅扩展(+188 行):孤儿清理矩阵(乱序匹配、四种输出类型互不背书、previous_response_id 放行、不相关 reference/compaction 不豁免、二次清理幂等);validateOpenAIResponsesToolOutputs 出错时历史必须原封不动并返回 ContinuationStateUnavailable;WS 兼容清理只对 OpenAI OAuth/SetupToken 生效、APIKey 与 Cindy 原样;raw WS 透传净化后幸存项字节不变且与解码路径共享同一官方孤儿判定、幂等;文本永不静默截断(10M 字符界限两侧、五种输出类型与嵌套 input_text),转发时超长输出原样送上游;OAuth 带 previous_response_id 的 HTTP 请求被本地拒绝且不发upstream、不丢工具结果。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: sanitize matrix L15-L81, validate contract L83-L154, WS account scope L156-L178, raw passthrough byte-identity + shared decision + idempotence L180-L251, named delegation preserved across history/previous combinations L253-L293, never-truncate L295-L344, OAuth anchor rejection with zero upstream bodies L346-L364, oversized output forwarded verbatim L366-L384.", - "Proves the input_compat.go delta plus the raw WS adapter in openai_gateway_request_body.go / openai_ws_v2 paths; the account-scope assertions match this slice's ownership requirement.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_responses_namespace.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "faadd4443273ff45190410ea74fed08ba881e6b983b1cee04782a3e175ba93b6", - "review_fingerprint": "faadd4443273ff45190410ea74fed08ba881e6b983b1cee04782a3e175ba93b6", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Codex namespace 工具在 Responses 命名空间上的往返策略。下游相对上游翻转与收紧:摊平仅限 OpenAI OAuth 且需账号开关(IsOpenAIOAuth 替代 OAuthLike;compact 端点保持既有摊平);API Key 保留历史调用项 namespace 的条件从『当前请求声明 namespace 工具』放宽为『声明或历史调用任一携带』(续写可省略 tools,新增 hasOpenAIResponsesToolCallNamespace);Cindy APIKey 一律保留;新增具名独立输出的单独保留开关(shouldKeepOpenAIResponsesStandaloneOutputNamespaces + isOpenAIResponsesNamedStandaloneOutput,call_id 为空/null 才算);摊平名映射登记/清除防止 failover 沿用上一账号映射。注释以 issue #4978/#4761 说明两套互斥上游要求。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: diff vs aea725f flips shouldFlattenOpenAIResponsesNamespaces to IsOpenAIOAuth (L45), rewrites shouldKeepOpenAIResponsesToolCallNamespaces with Cindy branch + variadic body + historical-call detection L84-L111, adds hasOpenAIResponsesToolCallNamespace L116-L133 and standalone-output gates L191-L204, stripOpenAIResponsesInputNamespaces gains the standalone keep flag L238-L286; flatten/restore map registration + clearing L288-L316.", - "Namespace flatten/restore algorithms live in internal/pkg/apicompat (core); no plugin duplicates this policy. Tool-call item type whitelist L180-L189 documented against codex-rs models.rs.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_responses_namespace_forward_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f666c933f670f35446c6e080e66999bbb603b9c3644cd8a5467283c65306bc62", - "review_fingerprint": "f666c933f670f35446c6e080e66999bbb603b9c3644cd8a5467283c65306bc62", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "上游已有测试,下游 diff 新增 Cindy 保留用例并把 fixture 模型改为 gpt-5.6-luna。经真实 Forward 断言 wire body:OAuth 原样转发 namespace 声明与历史调用项 namespace、非调用项残留清掉、不产生摊平名映射(回归 #4978);Cindy laxa profile 同样保留;API Key 声明命名空间工具(含 Responses Lite additional_tools 形态)时保留历史调用 namespace;compact 端点仍摊平并全量清理(#4761);账号开关恢复旧摊平行为并登记回程还原映射;failover 前清除上一账号的映射。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: diff adds TestOpenAIGatewayService_CindyPreservesCodexToolCallNamespaces L71-L95 and model rename L16; OAuth preservation + empty names map L37-L67, Lite carrier L121-L157, compact flatten L162-L183, legacy flag + restore map L186-L217, stale map cleared L221-L237.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_responses_rejected_field_retry_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6730cb15d6f2d1dfabd7d8bb489a198257c1261a27f71f397bf4d5a3c1ef3327", - "review_fingerprint": "6730cb15d6f2d1dfabd7d8bb489a198257c1261a27f71f397bf4d5a3c1ef3327", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "被拒字段反应式重试的测试主体为上游内容;下游 diff 反转三个用例以证明新策略:API Key 首次转发不再主动剥调用项 namespace(原样送达)、不再主动剥兼容供应商的 reasoning.content(由所选供应商自行校验)、无关字段重试全程保留调用 namespace。其余静态阅读证明:重试状态拒绝重复 body 且每账号受共享预算上限约束(failover 账号可重复同一变换);结构化 param 与错误文案必须一致才改写(歧义一律不重试);精确修复矩阵覆盖 namespace/status/null content/reasoning content 超长/truncation/max_output_tokens/prompt_cache_breakpoint/automation 根 type,同类型项一次清完避免逐索引耗尽预算。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: diff renames+reverses three tests (L521-L539 preserves call namespaces, L541-L567 preserves reasoning content with JSONEq, L626-L649 retry keeps namespaces); bounded state L21-L59, ambiguity matrix L61-L102/L335-L375, whole-type status clear L717-L739, exact indexed repairs with Forward round-trips L316-L413/L604-L624.", - "End-to-end proof that the namespace.go behavior flip reaches the wire; subject sources are core forwarding retries.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_responses_tool_schema_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "40959fb3acf9755596ccdb3f1df13160119a4ed24b99b4b5bc2035c862d6b532", - "review_fingerprint": "40959fb3acf9755596ccdb3f1df13160119a4ed24b99b4b5bc2035c862d6b532", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "上游已有的工具 Schema 净化测试;下游 diff 以删除为主(-267 行:约 15 个 lookaround/pattern 细粒度用例与 2 个基准被裁剪),仅 +12 行把分配次数守卫改为带环境变量的隔离子进程执行。保留用例静态阅读覆盖:parameters.type=null 修为 object(#5364,最小改动、缺失 type 不补写、重复键歧义不动、转义键处理、字节级保真含 1e+999/大整数/转义);平台边界表(OpenAI 才删 lookaround,Gemini/Antigravity/Composite 不修);failover 重放边界各兼容平台幂等修复;深度守卫不 panic;输入 body 不得就地改写;重写分配次数与命中数无关(复杂度守卫)。未执行任何测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: numstat vs aea725f = +12/-267; deleted funcs are the pattern battery (TestSanitizeOpenAIResponsesToolSchemaPatterns_* etc. per diff); added lines only wrap TestSanitize...RewriteCountIndependentOfHits in a subprocess with SUB2API_TOOL_SCHEMA_ALLOCATION_HELPER + cindyFeatureOnTestMainEnv (L366-L374).", - "Retained proofs: top-level/nested/Chat-shape repairs L15-L124, byte fidelity L136-L155, platform boundary L188-L211, replay boundary L213-L241, allocation guard L360-L399. Subject sanitizers remain in core source (not in this slice).", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/openai_satellite_policy_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7b1d0ef3c20321427d58a6b899904f28d7fa74b09ec8e1f350a60710d71f26c1", - "review_fingerprint": "7b1d0ef3c20321427d58a6b899904f28d7fa74b09ec8e1f350a60710d71f26c1", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试:证明 cyber_policy 安全拒绝在四个卫星入口一律终态——CC 直转的 failoverOpenAIUpstreamHTTPError 返回 nil 且不触发账号 temp 规则/错误落库并标记 ops CyberPolicy;alpha search 各种包裹形态(404/502 wrapper、Cindy 工具能力 400、Cindy SSE response.failed)都原样透传状态码、不 failover、不计费;images 错误处理不做二级 failover;Live 创建错误不换号。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Anchors: TestOpenAISatelliteCCSafetyRejectionPrecedesTemporaryErrorPolicy L18-38 (temp rule configured for the same status is NOT applied); TestOpenAISatelliteAlphaSafetyRejectionNeverUsesFallback L40-77 (errOpenAICyberPolicyForwarded, exactly 1 upstream request); TestOpenAISatelliteImagesSafetyRejectionCannotSecondaryFailover L79-104; TestOpenAISatelliteLiveSafetyRejectionRemainsTerminal L106-113.", - "Subjects: failoverOpenAIUpstreamHTTPError / ForwardAlphaSearch / handleOpenAIImagesErrorResponse / shouldFailoverLiveCreateError - the cross-endpoint safety-rejection contract added downstream (isOpenAIRequestScopedSafetyRejection call sites reviewed in openai_images_responses.go).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_setup_token_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fe244a7f954b5abf026acb1222699b5f4dde3fd9efce92c887f30b6f78b87c99", - "review_fingerprint": "fe244a7f954b5abf026acb1222699b5f4dde3fd9efce92c887f30b6f78b87c99", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Setup-token 账号按 Codex OAuth 语义工作的兼容测试:IsOpenAIOAuthLike/UsesOpenAICodexProtocol 分类、GetAccessToken 取 setup token、Images 走 OAuth direct 路径且 429 带同账号重试窗、WS URL/头/payload(store 强制 false)、CC 与 /v1/messages 桥用 Codex transform(system 提升、todo guard、turn-state 回放、tail 截断)。下游相对上游改 6 行:Codex 身份断言改用 resolveCodexOutboundIdentityForAccount 的账号级 UA,session 头断言从下划线 session_id 改为连字符 session-id——对应下游 Codex 探测加固(统一 TUI 身份、废弃下划线头)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: 3 assertion lines swapped (requireOpenAIMessagesCodexIdentity now takes resolveCodexOutboundIdentityForAccount(account, \"\").userAgent; upstream.requests[1] header key session_id -> session-id) in TestOpenAISetupTokenMessagesUsesCodexBridgeAndTurnState L216-236.", - "Also proves foreign-platform setup tokens are rejected by GetAccessToken and Grok setup-token WS URL falls back to api.openai.com (L126-128).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_sse_data.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ddfdf914bcdf8a40dff75939113ac19a0d74dfadc2ec1854a22f3341f7c9884c", - "review_fingerprint": "ddfdf914bcdf8a40dff75939113ac19a0d74dfadc2ec1854a22f3341f7c9884c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "SSE data 行累积与逐帧遍历工具:多行 data 拼接(合法 JSON 才合并)、[DONE] 忽略、frame 级 event type 推导。下游相对上游新增 6 行:forEachOpenAISSEFrame 里对单个 data 值先尝试 splitOpenAIConcatenatedJSONDocuments,把上游偶发拼接在同一行的多个 JSON 文档拆开逐个派发(各自重算有效事件类型),修复拼接文档被当作一个非法载荷丢弃的问题。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: +splitOpenAIConcatenatedJSONDocuments repair block in forEachOpenAISSEFrame emitData (L60-66).", - "Accumulator semantics unchanged: AddLine buffers data: lines until blank-line flush; joined multi-line payload only used when gjson.Valid (L86-100).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_sticky_compat.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d39565097e699b6bf3ee350aa9e2771b53aed352b739a400e064f750c8000f6d", - "review_fingerprint": "d39565097e699b6bf3ee350aa9e2771b53aed352b739a400e064f750c8000f6d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "粘性会话哈希迁移兼容层:当前格式 xxhash 与旧 sha256 双生成,读回退(fallback 命中计数)、双写(旧键 TTL 上限 10 分钟)、TTL 刷新兼容。下游相对上游把删除改为按期望账号的 compare-and-delete(DeleteSessionAccountIDIfMatches,expectedAccountID<=0 直接跳过),并且总是同时尝试两代键、用 errors.Join 保留双方错误——避免并发换绑被误删、也避免旧键残留把下一次回退读重新钉到已失效账号;新增导出 ClearOpenAIStickySessionAccountIDIfMatches。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: deleteStickySessionAccountID -> deleteStickySessionAccountIDIfMatches (L205-241, compare-and-delete both generations, errors.Join with rationale comment); +ClearOpenAIStickySessionAccountIDIfMatches L246-253.", - "Legacy hash travels via request context (withOpenAILegacySessionHash), legacy TTL capped at 10min (openAIStickyLegacyTTL L114-123); metrics are process-wide atomics for observability only.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_sticky_compat_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "af94e82d2e9d247fc344f0cbef543e6e5dbc415a1b3d4aa1acc0bbe696550b0e", - "review_fingerprint": "af94e82d2e9d247fc344f0cbef543e6e5dbc415a1b3d4aa1acc0bbe696550b0e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "粘性兼容层单测:旧键读回退命中并计数、双写开/关的行为差异为上游既有断言;下游新增五个删除语义测试——期望账号不匹配时两代键都保留(并发换绑不被误删)、匹配时两代键都删、legacy 删除失败可观察(errors.Is 命中且主键已删)、主/旧错误同时 Join 可分别匹配、删除调用顺序固定 primary→legacy;另含兼容回退指标快照测试。证明的是下游 compare-and-delete 修复。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f (+95): stickyDeleteFaultCache stub L13-30; TestDeleteStickySessionAccountIDIfMatches_PreservesConcurrentRebind L109-124 (bindings 22 preserved when expected 11); _DeletesExpectedDualBindings L126-140; _LegacyFailureIsObservable L142-161; _JoinsPrimaryAndLegacyErrors L163-186.", - "Subject is openai_sticky_compat.go's dual-generation compare-and-delete; SnapshotOpenAICompatibilityFallbackMetrics test covers ctxkey legacy fallback counters (core).", - "Test read statically only; not executed." - ] - }, - { - "path": "backend/internal/service/openai_token_provider.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "6f3364e915e58d484c67c97018bf48d4be2cbd70dd42d95c43e07380e0eddb8c", - "review_fingerprint": "6f3364e915e58d484c67c97018bf48d4be2cbd70dd42d95c43e07380e0eddb8c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "OpenAI OAuth access_token 提供者:缓存优先、到期前 3 分钟刷新、统一 OAuthRefreshAPI 或旧锁路径、锁竞争等待退避与指标、token 版本陈旧检查、缓存 TTL 依 expires_at 收敛。缺 refresh_token 且已过期属永久故障会置 error 并踢出调度;下游相对上游仅加 4 行守卫:isCodexTicketCredentialContext(ctx) 为真(codex-runtime 插件扩展宿主的 ticket 凭据路径,见 plugin_extension_accounts.go 注入)时不执行该永久禁用,防止插件的临时票据凭据把真实账号置错。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f: only the guard at L164-167 (if !isCodexTicketCredentialContext(ctx) { p.disableAccountMissingRefreshToken(...) }).", - "Call chain: withCodexTicketCredentials set in plugin_extension_accounts.go L59; also consulted by oauth_refresh_api.go L228 (ticketRefresh) - consistent ticket-credential carve-out across token paths.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_tool_continuation.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e1b62ecb5ffbf4d44cc3b29e117a8488e0ba237a23bd0c210feae14b57b43fdb", - "review_fingerprint": "e1b62ecb5ffbf4d44cc3b29e117a8488e0ba237a23bd0c210feae14b57b43fdb", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "工具续链信号分析:NeedsToolContinuation、单遍信号聚合、handler 热路径的 raw JSON 只读校验(避免大 input 全量解码)、以及剥离 previous_response_id 前的覆盖判定(每个工具输出的 call_id 必须能由 input 内同 call_id 的调用项或 item_reference 重建)。下游相对上游把覆盖分析重构为带 allowItemReferences 参数的共享实现并新增 AnalyzeConcreteToolCallOutputContextCoverageBytes:迁移换供应商场景要求具体工具调用项在同一载荷内,item_reference 依赖旧供应商存储的响应、不可携带;对象形态的单条 input 也统一处理。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S19-svc-openai-misc-2-review.json", - "Delta vs aea725f (+37): analyzeToolCallOutputContextCoverageBytes(body, allowItemReferences) L253-307 replaces the closure/ForEach form; +AnalyzeConcreteToolCallOutputContextCoverageBytes L245-247 (allowItemReferences=false); object input wrapped as single-item slice L259-263.", - "Consumers include the request-integrity comparator (NeedsToolContinuation gates id preservation) and handler pre-validation (ValidateFunctionCallOutputContextBytes with early-exit scan).", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/openai_tool_continuation_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "20bcb24e18a22ef31e4755daa6449a4990a9e779b8159eea666608312c4124e3", - "review_fingerprint": "20bcb24e18a22ef31e4755daa6449a4990a9e779b8159eea666608312c4124e3", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI Responses 工具续链判定的纯逻辑测试(329 行全读):覆盖 NeedsToolContinuation 的全部信号源、四种 Codex 工具输出类型、call_id 提取去重、item_reference 覆盖判定,以及 handler 侧 raw JSON 扫描与 service 侧 map 校验的语义一致性。下游相对上游 aea725f 新增 29 行:object 形态 input 的 single_object_tool_output_not_movable 用例(L266-L271)和 AnalyzeConcreteToolCallOutputContextCoverageBytes 的 RejectsStoredReferences 回归(L308-L329,item_reference 不算可迁移上下文)。被测函数属核心网关协议判定;静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S20-svc-openai-misc-3-review.json", - "git diff aea725f -- : +29/-0 — TestAnalyzeToolCallOutputContextCoverageBytes 新增 single_object_tool_output_not_movable 用例,新增 TestAnalyzeConcreteToolCallOutputContextCoverageBytes_RejectsStoredReferences", - "Call chain: 被测函数定义于 service/openai_tool_continuation.go;AnalyzeToolCallOutputContextCoverageBytes 由 openai_ws_forwarder_ingress.go:780 / openai_ws_forwarder_payload.go:769 消费;Concrete 变体无生产调用方(见 findings low)", - "Tests read statically only; not executed. No production behavior edit claimed." - ] - }, - { - "path": "backend/internal/service/openai_upstream_client_error_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3727193a04d0eeff00e2d34aba111aff71cf01119f5e5946ec1d76ea51ac21bd", - "review_fingerprint": "3727193a04d0eeff00e2d34aba111aff71cf01119f5e5946ec1d76ea51ac21bd", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 上游确定性 4xx 错误处理的测试(359 行全读,issue #5479):断言确定性 400 透传真实 type/code/param/message 而不被包成可重试 502、原生 Responses 与 compat 路径状态码/文案对称、非 JSON body 不 panic、401/402/403/404/422 仍归一 502 屏蔽上游账号状态、管理员透传规则优先于 400 分支、model_not_found 400 仅对可管理候选账号触发换号、脱敏 message 优先于原始 body(secret 不泄露)。下游相对上游仅 1 行:适配 failoverOpenAIUpstreamHTTPError 去掉 upstreamMsg 入参的下游签名(该值现于 openai_gateway_cc_pipeline.go:118 由 respBody 内部提取并脱敏)。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S20-svc-openai-misc-3-review.json", - "git diff aea725f -- : +1/-1 — TestFailoverOpenAIUpstreamHTTPError_ModelNotFoundIsNextAccountEligible 的调用去掉 \"model not found\" 实参,匹配下游 6 参签名(上游 7 参含 upstreamMsg)", - "Call chain: 被测 handleErrorResponse / handleCompatErrorResponse / writeOpenAIUpstreamClientError / isOpenAIDeterministicClientError 均在 core service;failoverOpenAIUpstreamHTTPError 定义于 openai_gateway_cc_pipeline.go:93,9 处网关端点调用均为 6 参形式", - "Tests read statically only; not executed. No production behavior edit claimed." - ] - }, - { - "path": "backend/internal/service/openai_upstream_transport_error.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "1f912aa7723ac60a34ad3a0838c2370137ebf31f53c6e09371e7fec435b79a3c", - "review_fingerprint": "1f912aa7723ac60a34ad3a0838c2370137ebf31f53c6e09371e7fec435b79a3c", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "传输层(代理/DNS/TCP/TLS,未拿到 HTTP 状态码)上游失败的分类与处置(197 行全读):typed 错误+字符串标记判定持久性,记 ops 事件(status 0, request_error),client 断连与插件已发出请求(PluginTransportError.RequestSent)时不换号。下游相对上游把\"持久故障立即十分钟冷却\"收窄到 IsOpenAIOfficialHTTPFailover 标记的官方 API-key HTTP 路径(冷却改用 BlockAccountSchedulingFromPersistedCooldown 作 DB 镜像,便于权威恢复清除),其余路径改为在 UpstreamFailoverError.Reason 携带新增的 transient/persistent 常量,由 handler 重试策略(openai_failover_retry.go:164,受 allowTransportRetry 限一次)与重试耗尽冷却(openai_account_runtime_block_fastpath.go:1788-1801)统一处置;tempUnschedule 守卫由 account==nil 换成 IsOpenAIOfficialHTTPFailover(对 nil ctx/account 返回 false,等价安全,见 openai_official_http_failover.go:20-30)。日志字段精简属可观测性微调。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S20-svc-openai-misc-3-review.json", - "git diff aea725f -- : 新增 OpenAITransient/PersistentTransportFailureReason 常量;handleOpenAIUpstreamTransportError 增加 IsOpenAIOfficialHTTPFailover 分叉(官方路径保留立即 tempUnschedule、不带 Reason;其余路径带 Reason 交下游链);tempUnscheduleOpenAITransportError 改用 BlockAccountSchedulingFromPersistedCooldown 并收窄守卫", - "Call chain: Reason 消费点 handler/openai_failover_retry.go:164(限一次同号重试)、service/openai_account_runtime_block_fastpath.go:1788-1801(persistent → retry_exhausted_transport 冷却),持久冷却责任从本文件迁移到重试耗尽链,无双执行器", - "No production behavior edit or test execution; classification traced statically only." - ] - }, - { - "path": "backend/internal/service/openai_upstream_transport_error_handle_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e8f019527064895d53b8e15f9fe5ef942e4c18edaa14a2aea31f45bd7dea442a", - "review_fingerprint": "e8f019527064895d53b8e15f9fe5ef942e4c18edaa14a2aea31f45bd7dea442a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "handleOpenAIUpstreamTransportError 的行为测试(//go:build unit,335 行全读):持久代理凭据失败返回带 OpenAIPersistentTransportFailureReason 的 failover 错误且不再立即写 DB 冷却或内存封禁(证明下游新语义\"分类交给有界重试链,重试前不动持久调度状态\")、瞬时错误换号不驱逐、context.Canceled(含 wrapped)不换号不驱逐、DeadlineExceeded 仍换号、service 不抢写响应体、ops 事件带 proxy id/name、forwardAsRawChatCompletions 逐账号记录代理、Ollama Cloud 活跃度只记 ollama.com 账号且 Canceled 不记。下游相对上游改写持久用例断言(原 PersistentEvictsAndFailsOver → PersistentClassifiesWithoutDurableMutation)并删除因 tempUnschedule 新守卫(未标记 ctx 直接早退)而失效的 nil-repo 用例。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S20-svc-openai-misc-3-review.json", - "git diff aea725f -- : +7/-32 — 持久用例改断言 fo.Reason==OpenAIPersistentTransportFailureReason、repo.tempUnschedCalls 为空、isOpenAIAccountRuntimeBlocked 为 false;删除 TestTempUnscheduleOpenAITransportError_NilAccountRepo_InMemoryBlockOnly", - "断言与源文件下游语义一一对应:测试账号未标记 official HTTP 路径(无 AccountTypeAPIKey/ctx 标记),走 Reason 分支——与 openai_upstream_transport_error.go 的 IsOpenAIOfficialHTTPFailover 分叉一致", - "Tests read statically only; not executed (unit build tag). No production behavior edit claimed." - ] - }, - { - "path": "backend/internal/service/openai_v183_compat.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0a297989ee05807bb4f080b0f70a87b00e641ca512cca16124ccbe0f7ef60bb3", - "review_fingerprint": "0a297989ee05807bb4f080b0f70a87b00e641ca512cca16124ccbe0f7ef60bb3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "下游新增文件(上游 ls-tree 无此路径,整文件即 delta,410 行全读)的 OpenAI 网关兼容工具集:WS 事件信封解包、SSE 事件类型解析、usage 非零合并、限频 missing-usage 告警采样器(单例原子计数,有界)、转发模型映射解析、workspace/org 停用类 access-state 检测(OpenAIUpstreamAccessStateReason 由 openai_gateway_upstream_errors.go:594 与 handler:4554 消费)、容量 shed 文案、流内 401/凭据失败分类、WS 客户端可见失败的 ops 标记、HTTP response 归属绑定/校验、带预算拒绝 request-scope 与 Cindy Laxa model_not_supported 界定的 failover 构造器(Cindy 界定按账号 provider profile 收窄、有注释说明为何留在通用构造器)、antigravity 连通性测试默认模型(account_test_service.go:2524 使用)。逐符号 rg 验证除 SetOpenAIHTTPResponseOwner / ValidateOpenAIHTTPResponseOwner 外均有生产调用方;这两个归属校验入口相对上游丢失 handler 接线,构成 high finding,故记 pending 待修复后复审。静态阅读,未执行。复审于 6258adab5:owner 接线已在 handler 恢复——openai_gateway_handler.go L589-L607 在任何策略查询/账号调度前调 ValidateOpenAIHTTPResponseOwner(查询出错或不归属均回 400),L610 对每个放行请求调 SetOpenAIHTTPResponseOwner;bindHTTPResponseAccount(openai_gateway_response_handling.go L1672-L1675)经 openai_gateway_forward.go L1131/L1517 与 openai_gateway_passthrough.go L682 可达,链路已活。本文件字节未变(sha 一致),复审同为静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S20-svc-openai-misc-3-review.json", - "git ls-tree aea725f -- 为空:文件为下游新增,整文件按 delta 审查;18 个导出/包级符号逐一 rg 调用方计数,仅 Set/ValidateOpenAIHTTPResponseOwner 无生产引用", - "Call chain: bindOpenAIResponseAccount(openai_gateway_response_handling.go:1672-1675)消费 owner context key 但无人写入;上游 aea725f handler L496-L531 有完整校验+登记链;下游 handler 仅 ParseOpenAIContinuationAnchor 格式校验(openai_gateway_handler.go:583-588);复审 6258adab5 后 handler L589-L610 已恢复校验+登记,Set/Validate 均有生产调用方", - "No production behavior edit or test execution; WS v2 路径的会话身份处理未在本 slice 深审,finding 仅限 HTTP 路径。" - ] - }, - { - "path": "backend/internal/service/openai_ws_account_sticky_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d0f3a67469e4a8e6aba53de52bd410b64efb54c2683afbbd8264f598b2a73eba", - "review_fingerprint": "d0f3a67469e4a8e6aba53de52bd410b64efb54c2683afbbd8264f598b2a73eba", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "previous_response_id 粘连选号(SelectAccountByPreviousResponseID 及 capability/strict 变体)的单测,612 行。下游相对上游 aea725f 新增/改动的断言:状态存储读失败必须 fail-closed 返回 503 的 continuation-state-unavailable;Cindy HTTP→WSv2 桥接账号在开关开启时命中、关闭时 miss;迁移后调度快照里的陈旧行不得覆盖 canonical Cindy 身份(返回 Platform=cindy、canonical ID);限流/配额 auto-pause 造成的 miss 保留绑定(上游原断言 require.Zero 即清除绑定,下游改为保留以便窗口重置后续链);strict 续接对 Laxa passthrough 能力不匹配与 canonical 模型冷却 fail-closed。被测主体在 openai_ws_forwarder_support.go(宿主调度机制)。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: TestOpenAIGatewayService_SelectAccountByPreviousResponseID_StoreErrorFailsClosed L14, _UsesCanonicalCindyIdentityAfterMigration L101, _RateLimitedMissPreservesBinding L206 (diff flips require.Zero to require.Equal on the kept binding), _StrictPreviousResponsePolicyMismatchFailsClosed L509, _StrictPreviousResponseModelCooldownUsesCanonicalLaxaKey L555; subject SelectAccountByPreviousResponseID at openai_ws_forwarder_support.go L534.", - "Diff vs aea725f: +218 lines of new cases; helper newOpenAIWSV2TestConfig unchanged shape.", - "Static read only; the test was not executed and no production behavior was exercised." - ] - }, - { - "path": "backend/internal/service/openai_ws_client.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3dae0ea5ccdaf8058c03a7b9ccd027ba8a642be39218fe703cdd85afe3a4a041", - "review_fingerprint": "3dae0ea5ccdaf8058c03a7b9ccd027ba8a642be39218fe703cdd85afe3a4a041", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "coder/websocket 拨号器与按代理 URL 缓存的 HTTP client,424 行。下游相对上游仅两处:直连握手改用 openAIWSDirectHTTPClient(sync.Once 单例,克隆 DefaultTransport 并 DisableCompression);代理 transport 同样加 DisableCompression——使握手不带 Go 自动附加的 Accept-Encoding: gzip,与官方 Codex 客户端一致。缓存有界且有清理:256 条上限(ensureProxyClientCapacityLocked 逐出最旧)、15 分钟 idle TTL(cleanupProxyClientsLocked),逐出时 CloseIdleConnections;读上限 16MB;openAIWSHandshakeError 保留 8KB 响应体供 Agent Identity 恢复路径区分 401 原因,不写日志。属于宿主通用传输机制。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: Dial L115 (else branch L141-143 new), proxyHTTPClient L171 (DisableCompression L201), openAIWSDirectHTTPClient L221-233 (new), cleanupProxyClientsLocked L235 / ensureProxyClientCapacityLocked L257 bound the cache, SupportsIdlePingWithoutReader=false + RequiresReaderLoop=true contract L399-406.", - "Diff vs aea725f: +26 lines only (direct-client singleton and the two DisableCompression sites); no business rule present.", - "Static read only; no dial or network was performed." - ] - }, - { - "path": "backend/internal/service/openai_ws_fallback_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b8b2908e3618b232d8d70d9b2673a5e34d8a96bfa8942819390357035cacd2ce", - "review_fingerprint": "b8b2908e3618b232d8d70d9b2673a5e34d8a96bfa8942819390357035cacd2ce", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "WS 错误分类与回退行为单测,350 行。下游相对上游唯一新增 TestOpenAIWSInitialDialFailover(+40 行):401/429 立即换号、5xx 与网络错误同账号重试一次(网络错误归为 OpenAIPersistentTransportFailureReason/502)、普通 400 与普通结构化 model_not_supported 保持终止、legacy Laxa 账号(base_url=api.laxarouter.ai)的结构化 model_not_supported 立即换号(openAIModelNotSupportedReason)、本地连接队列满不算上游失败。其余为上游已有的 classify/summarize/cooldown/backoff/store-disabled 模式与 payload 采样测试。被测 openAIWSInitialDialFailover 在 support.go L400。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: TestOpenAIWSInitialDialFailover L64-102 table incl. legacyLaxa case L85; TestOpsUpstreamWSProxyAttributionNeverReportsDirect L246 proves no managed proxy reports unknown, never direct; subject openAIWSInitialDialFailover at openai_ws_forwarder_support.go L400.", - "Diff vs aea725f adds only the failover table test; all other cases pre-existed upstream.", - "Static read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "7064f7a432199436b3724ebebb4f867698dd2d67e8f276fd8ea395a9d2a2daa4", - "review_fingerprint": "7064f7a432199436b3724ebebb4f867698dd2d67e8f276fd8ea395a9d2a2daa4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "WS 转发公共层(错误类型、重试门、Hooks、超时/采样配置),审阅的是 63a98c8cc 之后的当前 496 行字节(比切片版本新增 CopyProviderPricingContext 钩子)。下游相对上游:turn 错误拆出 openAIWSIngressTurnTransportCause(仅 write_upstream/read_upstream、未写下游、非 ctx 取消才算传输失败);shouldRetryOpenAIWSIngressTurn 限定 turn==1 且 retry<1;normalizeOpenAIWSNonInitialTurnError 把非首轮失败规范化为 1013 close,但保留 request-scoped 的 UpstreamFailoverError(!ShouldRetryNextAccount)以便 handler 发稳定 response.failed,阻断跨账号重放;新增 invalid_encrypted_content stage 常量与 openAIWSCurrentTurnFailoverError 载荷隔离拷贝。63a98c8cc 增加 hooks.CopyProviderPricingContext 与 copyOpenAIWSProviderPricingContext:hooks 缺省时原样返回 base ctx,回调返回 nil ctx 视为 ErrExtensionOperationUnavailable——把账号绑定的目录/定价快照按 turn 注入 ctx,机制在宿主、快照内容由调用方提供。静态阅读。", - "evidence": [ - "Full-file static review (current bytes re-read whole after the freeze): artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: openAIWSIngressTurnTransportCause L169-186, shouldRetryOpenAIWSIngressTurn L188-190, normalizeOpenAIWSNonInitialTurnError L209-229, OpenAIWSIngressHooks.CopyProviderPricingContext L304-306 and copyOpenAIWSProviderPricingContext L313-325 (added by 63a98c8cc), acquire timeout no longer stacks write timeout L488-496.", - "sha256 recomputed from disk at HEAD 05e25bdf2; file bytes equal the frozen 63a98c8cc blob (git status clean for this path).", - "Static read only; no execution." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_client_cancel_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ea551e2ec01bc441ad4121210fb9a820b101cb9e8f95099cdea71c163ef3349c", - "review_fingerprint": "ea551e2ec01bc441ad4121210fb9a820b101cb9e8f95099cdea71c163ef3349c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "客户端取消后的 drain 语义单测,329 行。断言证明:客户端首写即取消时仍 drain 到 response.completed 并保留 usage/RequestID/RequestedReasoningEffort,不把取消当上游失败也不给已取消客户端写伪造 response.failed;usage-then-EOF 不虚构成功终态(err=context.Canceled);失败终态在取消后保持 failed;drain 预算是总额 1 秒而非每次读 1 秒;下游写失败时 drained terminal 不 commit 握手 turn-state(GetSessionTurnState(group,hash,accountID) 仍为 prior 值,键含 account.ID);classifyAccountTrafficOutcome 表格(429/503/cancelled-wins/failed-terminal-status/empty-terminal 不算成功)。被测为 forwardOpenAIWSV2 与 account_traffic_observe.go L222 的宿主机制。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: TestForwardOpenAIWSV2_ClientCancellationDrainsWithoutSyntheticFailure L22, _DisconnectedDrainPreservesTerminalAndCommitBoundaries L60 (drain_budget_is_total_not_per_read L85, failed_downstream_write_does_not_commit_drained_state L97), TestClassifyAccountTrafficOutcome L307; helper openAIWSCancelSafeConn keeps a delayed event for detached-context drain L260.", - "Diff vs aea725f: +183 lines (new boundary table, writeErr injection, outcome classification test).", - "Static read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_ingress.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "b755f2d0247ca13b66d51f4bdf00f75354d006a086d7e65761ee0d2d41dc73b4", - "review_fingerprint": "b755f2d0247ca13b66d51f4bdf00f75354d006a086d7e65761ee0d2d41dc73b4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "入站 WS 会话主循环(ProxyResponsesWebSocketFromClient,当前 2204 行,审阅 63a98c8cc 冻结字节:完整读 062465f6e 版本+全量累计 diff+变更区重读)。下游相对上游重写续接/重试合同:session turn-state 键加 account.ID(GetSessionTurnState(groupID,sessionHash,account.ID),L721)且 handshake state 只在真正写下游后才 commit(commitTurnState L1185,经 rawWriteClientMessage 回调触发);previous_response_not_found 仅在本连接已验证完整基线时做一次 verified full replay(openAIWSReplayHistoryVerified),否则以 request-scoped continuation 错误稳定终止(不换号/不罚健康分/原始错误不写客户端);严格 Cindy 续接(IsCindyAPIKeyAccount 或带锚点的 legacy Laxa)强制 resolveStrictCindyAnchorConn(L682)绑定连接 fail-closed 并禁走 passthrough;preflight ping 失败一律 1013 关闭、绝不换连重放(L1966+,上游原自动重连并可丢锚点重放);store=false 会话 pin 连接、defer releaseSessionLease(L1652)统一 MarkBroken/Unpin/Release;invalid_encrypted_content 改为立即终止(删除上游的会话级密文血统剥离);error 事件先做 cindyBalanceTerminalFailover、容量降载码只改写客户端副本;每 turn beginBusinessSystemPromptRequestTurn(L535)替换指针释放上一 turn 提示词快照(e672558dd 修复)。业务规则均委托无第二执行体:业务系统提示词经 applyBusinessSystemPromptForRequest/rewriteBusinessSystemPromptCacheKey(内部经 extension invoker 咨询 prompt-skills 插件),Cindy 余额/身份/模型经 cindy_* 助手。63a98c8cc 后每 turn 经 copyOpenAIWSProviderPricingContext(L315/L838/L1164)取账号绑定定价快照 ctx,模型映射改经 resolveOpenAIForwardModelContext 与 resolveLegacyCindyOpenAIModelContext(policyCtx,...),sendAndRelay 的 mappedModel 提前解析。发现一处低危冗余(见 findings)。静态阅读。", - "evidence": [ - "Full static review of the prior committed version plus the complete cumulative diff 062465f6e..HEAD (only commit 63a98c8cc) and re-reads of every changed region: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors (current bytes): strictCindyContinuation routing L134-160, parseClientPayload pricing ctx L315 and model resolution L331-364, prompt turn begin L535, resolveStrictCindyAnchorConn L682, session turn-state key with account.ID L721, commitTurnState L1185, pin/unpin + releaseSessionLease L1624-1668, prepareCindyFullReplay L1698, recoverIngressPrevResponseNotFound L1715, retryIngressTurn L1760, preflight ping fail-close L1966+.", - "Boundary check: turn-state keyed by groupID+sessionHash+accountID; responseID->account and responseID->conn bindings TTL-bounded (openAIWSResponseStickyTTL/openAIWSSessionStickyTTL); replay history slices are session-local and released with the session; combine builds fresh slice headers (no shared-array append).", - "sha256 recomputed from disk at HEAD 05e25bdf2 (frozen 63a98c8cc blob); duplicate persistOpenAIWSRateLimitSignal at L1357/L1439 recorded in findings.", - "Static read only; no execution, no production traffic." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_ingress_session_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d770875b76f0f52bf67b82966f3d1186190ca4d039accd62ddef553bffb07a39", - "review_fingerprint": "d770875b76f0f52bf67b82966f3d1186190ca4d039accd62ddef553bffb07a39", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "入站 WS 会话级集成测试,5460 行,httptest 真 WS 服务器+假上游连接。断言具体证明:下游写 ctx 的取消所有权(lease 丢失不打断进行中的写、lifecycle 取消直达且保留 cause);Cindy 余额终态顺序(输出前→CindyBalanceInsufficient failover 且 budget_exceeded/敏感消息不下发,输出后→1013 且客户端只见 sanitize 后事件,首个信号不落库 markCalls=0);turn-state 只在写下游后 commit(重连 B 不带 A 的未提交 state,session store 最终为 B,origin 绑定 account.ID);同会话多 turn 复用同一 lease/连接且业务提示词每 turn 恰好注入一次、prompt_cache_key 改写为 64 位 hex 且跨 turn 稳定、握手 session_id 回退用最终 wire key;lease 丢失→1013 capacity lease lost;idle 超时释放 store=false 会话(池断言 unpin+release);后续 create 可省略 model;codex image bridge 的 lite/非 lite/函数工具三分支与 installation/sandbox 身份收敛;dedicated 模式跨会话不复用连接;passthrough 直连转发、畸形边界帧不 dial 直接拒绝、握手剥离无来源 turn-state 且 session-id 做账号作用域映射;http_bridge 模式走 HTTP 上游并回传 usage/cached tokens;mode off→PolicyViolation;store=false 外部锚点不被删除/替换/拼接历史;preflight ping 失败四变体一律 1013 不换连重放、第二连接零写入;store=true 跳过 strict 评估;function_call_output 自动回填 previous_response_id 及跳过条件(上一轮无 response.id、已带 tool 上下文;仅 item_reference 时仍回填);第二轮写失败→1013 且 Before/AfterTurn 每 turn 恰一次;第二轮 previous_response_not_found→request-scoped 稳定错误不跨连重放(重复键场景同样);续接错误隔离表 8 案例(原始上游错误不写客户端、锚点不被改写、dial 数受限、可 seed 绑定连接);拒收 msg_ 锚点;首轮仅元数据失败重试一次且 attempt-1 的 response.id 不泄漏;客户端断连仍 drain 上游并保留旧账号 turn-state;invalid_encrypted_content 不污染同会话后续连接(密文/summary/phase/扩展字段原样上送,状态库无血统记录)。仅静态阅读,此 207KB 测试未被执行。", - "evidence": [ - "Full-file static review in 11 sequential chunks to EOF: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: TestOpenAIWSDownstreamWriteContext_CancellationOwnership L92, TestOpenAIWSIngressCindyBalanceTerminalWriteOrdering L137, TestOpenAIWSIngressTurnStateCommitsOnlyAfterDownstreamOutput L284 (headers[1] empty + turn-state-B committed L387-399), KeepLeaseAcrossTurns L401 (1 acquire/1 dial/2 writes, business-server once per write, 64-hex cache key L554-563), ContinuationErrorEventsAreIsolated table L4254-4476, FirstTurnMetadataFailureRetriesWithoutLeak L4873, ClientDisconnectStillDrainsUpstream L5114 (old account state kept L5272-5283), InvalidEncryptedContentPreservesNextConnectionPayload L5285 (JSONEq input preserved, HasAnySessionInvalidEncryptedContent false).", - "Renamed tests vs upstream show the contract flips: PreflightPingFail*Reconnects -> *ClosesWithoutReplay, PrevResponseStrictDropToFullCreate -> PreviousResponsePreservedAcrossAnchorAndConfigChanges, PreviousResponseNotFoundRecoversByDroppingPrevID -> SecondTurn...StableErrorWithoutReplay.", - "Static read only; this test file was NOT executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_ingress_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cffaf3524deff530274d068aa463825c82dc02beb3541844c3c414cd775d157e", - "review_fingerprint": "cffaf3524deff530274d068aa463825c82dc02beb3541844c3c414cd775d157e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "入站 WS 纯函数单测,1137 行。断言证明:客户端断连错误分类(EOF/reset/broken pipe/1000/1001/1005/1006 为断连,PolicyViolation 不是);normalizeOpenAIWSNonInitialTurnError 阻断非首轮跨账号重放(429 failover 在 turn2 变 1013 close 且 ErrorIs 保留原因,continuation 错误原样透传);shouldRetryOpenAIWSIngressTurn 仅 turn1、零输出、retry<1(含持久网络错误);prev-not-found stage 判定需未写下游;drop/set/align previous_response_id 助手(重复键、畸形 JSON best-effort、最多 8 遍删除);spark 与通用 image 工具剥离;replay input 序列构建的零拷贝/所有权断言(combine 新建头数组、正文共享底层数组)与孤儿 tool_call 保留策略(diff 把 filters_orphan 改名 preserves_unfinished:未完成历史项现被保留);shouldKeepIngressPreviousResponseID 的 keep/drop 理由表;shouldInferIngressFunctionCallOutputPreviousResponseID 条件表。静态阅读,未执行。", - "evidence": [ - "Full-file static review in 3 chunks: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: TestNormalizeOpenAIWSNonInitialTurnErrorStopsCrossAccountReplay L51-84, TestShouldRetryOpenAIWSIngressTurnOnlyAllowsFirstTurnWithoutOutput L86-97, TestBuildOpenAIWSReplayInputSequence orphan-preserve subtests L905-976, TestOpenAIWSReplaySequenceSharesBodies zero-copy asserts L1085-1137, TestShouldInferIngressFunctionCallOutputPreviousResponseID table L381-490.", - "Diff vs aea725f: +63/-14 lines (two new tests, orphan-filter subtests flipped to preserve semantics).", - "Static read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_logutil.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a80a260883f4c11b737dc904072f05543b595043ef34e697673c57a417987c0f", - "review_fingerprint": "a80a260883f4c11b737dc904072f05543b595043ef34e697673c57a417987c0f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "WS 日志/事件解析工具集,685 行,大部分与上游一致(值截断、事件包络解析、usage 提取、dial 错误分类、断连判定、input 摘要)。下游 delta 恰好两处且都是行为修正:applyOpenAIWSRetryPayloadStrategy 不再在重试 attempt>=2 时删除 include 字段(include 可能声明下一轮所需的 reasoning.encrypted_content,删除会改变请求语义),一律返回 full 并删除了 dropOpenAIWSPayloadKey 助手;logOpenAIWSBindResponseAccountWarn 不再把原始 response_id 写进日志,改记 present 布尔与 kind 分类(日志脱敏)。静态阅读,未执行。", - "evidence": [ - "Full-file static review in 2 chunks: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: applyOpenAIWSRetryPayloadStrategy L483-488 (always full; upstream trimmed include at attempt>=2), logOpenAIWSBindResponseAccountWarn L509-521 (response_id_present/response_id_kind instead of raw id), isOpenAIWSClientDisconnectError L637-659 unchanged vs upstream.", - "Diff vs aea725f: two hunks only (+35/-...); the retry-strategy flip is proven by openai_ws_forwarder_retry_payload_test.go.", - "Static read only; no execution." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_payload.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "acca6f196e2f8fc8d9a814b7708777adf0c2a2b2d8284a25ab2b3be0c76d4cf0", - "review_fingerprint": "acca6f196e2f8fc8d9a814b7708777adf0c2a2b2d8284a25ab2b3be0c76d4cf0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "WS URL/握手头构造与 replay 载荷助手,892 行。下游相对上游(+92/-81):buildOpenAIWSHeaders 接入 Codex 身份链——Codex 协议账号只发连字符 session-id/thread-id(不再发下划线 session_id/conversation_id)、applyOpenAICodexTicket、staged 指纹头、enforceCodexIdentityHeadersForAccountContext 统一 UA/originator、guardOpenAICodexTurnStateEcho 阻止跨账号 turn-state 回带、软路由 hint 与诊断日志;prompt_cache_key 回退值由调用方传入最终线上值不再二次映射。replay 助手重写为可验证证明链:删除上游的孤儿 tool_call 清洗(openAIWSRawItemsHaveToolCallContextForOutputs/sanitizeHistoricalReplayToolCalls),新增 openAIWSReplayHistoryVerified(锚点必须等于已验证基线 responseID 且无 conversation 引用)、prepareCindyContinuationReplayPayload(经 ClassifyCindyContinuation 分类后才允许去锚)、buildOpenAIWSCurrentTurnRetryPayload(跨账号重试需 verified 历史+CanSwitchAccount+tool 上下文全覆盖)、prepareOpenAIWSVerifiedReplayPayload。零拷贝所有权不变式成文(unsafe 视图、combine 新建头数组)。Cindy 分类本体在 openai_cindy_continuation.go,此处只是机制调用方。静态阅读。", - "evidence": [ - "Full-file static review in 2 chunks: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: buildOpenAIWSHeaders L78-208 (codex ticket L136, hyphen-only session headers L125-132/L144-153, identity enforcement L184-188, turn-state echo guard L195), ownership invariant comment L448-451, openAIWSReplayHistoryVerified L785-795, prepareCindyContinuationReplayPayload L712-739, buildOpenAIWSCurrentTurnRetryPayload L741-774 (coverage gate L769-772), strict-state comparators L805-892.", - "Deleted vs upstream: openAIWSRawItemsHaveToolCallContextForOutputs and sanitizeOpenAIWSHistoricalReplayToolCalls (history sanitize replaced by verified-baseline proofs).", - "Static read only; no execution." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_retry_payload_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "29b6cc360483c321c42554d76c9c4f1feea90391e86b64b03bd7b89e09cf7408", - "review_fingerprint": "29b6cc360483c321c42554d76c9c4f1feea90391e86b64b03bd7b89e09cf7408", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "51 行小测试,只测 applyOpenAIWSRetryPayloadStrategy。下游把上游断言从 trim_optional_fields/删除 include 翻转为 full/removed 为空,并新增断言 include=[reasoning.encrypted_content] 在 attempt=3 与 attempt=6 时都原样保留(prompt_cache_key、instructions、tools、tool_choice、text 同样保留)——证明重试不再改变请求语义的修复。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: TestApplyOpenAIWSRetryPayloadStrategy_KeepPromptCacheKey L9-27 and _AttemptSixKeepsSemanticFields L29-51; subject at openai_ws_forwarder_logutil.go L483.", - "Diff vs aea725f flips the expected strategy and adds the include-preserved assertions.", - "Static read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_success_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8e330eeb20ca02e32a167051ce6fbe71410e3d996aa007bf5f6eb850a9623fbb", - "review_fingerprint": "8e330eeb20ca02e32a167051ce6fbe71410e3d996aa007bf5f6eb850a9623fbb", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "HTTP→WSv2 转发(forwardOpenAIWSV2/Forward)成功路径集成测试,2071 行,gorilla WS 假上游或 captureConn。断言证明:WSv2 成功不落 HTTP 且 responseID→账号/连接双绑定(sticky store);校验解码后的补丁体上送(max_completion_tokens 被剥离);图片输出计数/尺寸档/计费模型;completed 事件上模型回写原始请求模型且 apply_patch→edit 工具名修正;response.failed 不算调度成功并触发 runtime block;正常终端后连接归还复用(条件式 MarkBroken,1 次 upgrade 服务 2 请求);OAuth 默认 store=false、强制 stream=true、原生 namespace 保留;无效原生工具项 ID 清洗(fc_→ctc_);originator/UA 收口为网关规范身份(账号级自定义 UA 保留指纹但重建版本段);缺会话头时以 prompt_cache_key 补连字符 session-id(账号作用域映射,下划线头不再发送——diff 将 isolateOpenAIUpstreamSessionID 断言换成 scopeCodexAccountIdentityValue+session-id);指纹模式握手/帧体一致性(installation 只在 body client_metadata);response.done 的 usage 细项(cache read/creation/image tokens);WSv1 不支持时 400 且不触发 HTTP 上游;重连时 turn-state 从会话存储回放到握手头(键为 resolveOpenAIWSExecutionScope+account.ID);generate=false 预热两次写且预热读受父 ctx 控制;连接复用时 turn metadata 落帧体;store=false 会话级连接隔离/关闭强制新连时允许复用;read timeout 按每次读独立计算。静态阅读,未执行。", - "evidence": [ - "Full-file static review in 5 chunks to EOF: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: Forward_WSv2_SuccessAndBindSticky L26 (store bindings L163-169), _PoolReuseNotOneToOne L618 (upgradeCount==1 L723), _OAuthStoreFalseByDefault L729 (hyphen session-id L800-804), _CodexFingerprintHandshakeBodyParityAndDefaultCacheKey L1101, _TurnStateAndMetadataReplayOnReconnect L1316 (execution-scope + account.ID key L1409-1414), _GeneratePrewarm L1437, _WSv2StoreFalseSessionConnIsolation L1640, _WSv2ReadTimeoutAppliesPerRead L1845; capture fakes L1923-2071.", - "Diff vs aea725f (+53): identity assertions flipped to hyphen-only account-scoped session headers and body-only installation id; writeSignals sync added to captureConn.", - "Static read only; the test was not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_support.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "25380932466d50560e196c57959a6cb1abe8a89ca33ab828129b15ca7153a94b", - "review_fingerprint": "25380932466d50560e196c57959a6cb1abe8a89ca33ab828129b15ca7153a94b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "WS 预热、错误分类与 previous_response_id 粘连调度,1167 行。下游相对上游(+596/-...):预热 error/response.failed 识别 Cindy model_not_supported 并转结构化 failover(同账号尝试内冷却 pair);openAIWSPayloadStatus/TransientStatus 拆分(容量降载码 503、rate_limit 429 等映射);handleOpenAIWSFailureAccountSideEffects 统一凭据失败与瞬态失败并防止 error/failed 成对重复落库;openAIWSInitialDialFailover 新增(401/403/429 立即换号、5xx/网络重试一次、Cindy 结构化 model_not_supported 立即换号、本地池压力不算上游失败);粘连选号扩展为 WithPolicy/AndMismatch 链:previousResponseBindingRequiresStrictContinuation 按绑定属主是否 Cindy 运行时账号决定策略不匹配 soft-miss 还是 fail-closed,ClassifyLegacyLaxaAccountPool 区分混合池;resolve 路径逐项校验(排除表、DB 权威身份、调度阈值、组/隐私匹配、模型支持、端点能力、配额 auto-pause 与利润 veto 保留绑定 soft-miss、compact 档删除绑定);persistOpenAIWSRateLimitSignal 语义 429 仅 spark+OAuth 保留握手头,其余置 nil 防止全局快照误伤账号级限流;markOpenAIWSClientVisibleFailure 与 newOpenAIWSRateLimitFailoverError 迁至 openai_v183_compat.go(非删除)。Cindy 身份判定与余额事件委托 cindy_identity/cindy_balance;此文件持有的是通用调度与分类机制。静态阅读。", - "evidence": [ - "Full-file static review in 3 chunks: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: performOpenAIWSGeneratePrewarm L24-209 (model_not_supported failover L163-168), openAIWSInitialDialFailover L400-451, selectAccountByPreviousResponseIDForStrictContinuation L596-645, previousResponseBindingRequiresStrictContinuation L691-737, resolveAccountByPreviousResponseIDForCapability L818-942 (auto-pause keeps binding L929-931), persistOpenAIWSRateLimitSignal L995-1013 with openAIWSSemantic429Headers L1015-1020.", - "Moved-not-deleted check: markOpenAIWSClientVisibleFailure at openai_v183_compat.go L269, newOpenAIWSRateLimitFailoverError at openai_v183_compat.go L400.", - "Static read only; no execution." - ] - }, - { - "path": "backend/internal/service/openai_ws_forwarder_v2.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "255f915f4e6e0b4bcd4299d4d8d50d307bda32c2b4cc6636a0a26769be158aa7", - "review_fingerprint": "255f915f4e6e0b4bcd4299d4d8d50d307bda32c2b4cc6636a0a26769be158aa7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "HTTP 入口→WSv2 上游的单 turn 转发(forwardOpenAIWSV2/WithScope),1106 行。下游相对上游(+313):新增 WithScope 变体,turn-state 与 store=false 连接绑定按执行作用域+account.ID 取键;Cindy HTTP→WSv2 桥接(decision.Reason)强制上游 stream=true、首轮事件走 cindyHTTPToWSV2FirstTurnEventFailover、拨号瞬态失败不在桥接内重复落账号状态;staged 请求完整性校验与 staged 指纹 client_metadata;握手 turn-state 拆 stage(写响应头)与 commit(写下游成功后才入会话存储,JSON 路径检查 c.Errors 增量);客户端断连转 detached ctx drain 且以 read_timeout 为总预算;粘连 JSON 文档拆分修复与非法事件 JSON 处理;cindy 余额终态 failover(输出前换号、输出后 sanitize 重试事件);cyber policy failover/清洗;Cindy model_not_supported 结构化 failover;refusal recovery 输出包装;首 token 前缓冲非 token 事件保证可安全回退 HTTP;正常终端 cleanExit 才允许连接回池(pendingJSONDocuments 有尾帧则不复用)。业务判定均委托(cindy_balance、cyber policy、refusal、模型映射)。静态阅读。", - "evidence": [ - "Full-file static review in 3 chunks: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: forwardOpenAIWSV2WithScope L44, execution-scope session key L163-179 (GetSessionTurnState with account.ID L176), stage/commit turn-state split L372-389 with emitStreamMessage commit L538-557 and JSON commit L1045-1051, prewarm call L391-403, detached drain L456-479 and total budget L616-626, concatenated JSON repair L629-639, cindy balance failover L695-715, cyber policy L815-838, cleanExit contract L308-317/L996-1000.", - "Boundary: responseID->account/conn bind at L1056-1060 and store=false session conn bind L1061-1063, both TTL-bounded.", - "Static read only; no execution." - ] - }, - { - "path": "backend/internal/service/openai_ws_http_bridge.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "12d67721ceb6ee548e07890119c076daebe833c6e464fec5e65000f09022730d", - "review_fingerprint": "12d67721ceb6ee548e07890119c076daebe833c6e464fec5e65000f09022730d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "入站 WS→HTTP 上游的桥接 turn(proxyOpenAIWSHTTPBridgeTurn)与桥接判定/工具集,1111 行。下游相对上游(+331/-...):新增 openAIWSHTTPBridgeTurnState——桥接自证的 turn-state 只随该桥接请求头出站(accountID 必须匹配当前账号),绝不进入共享原生 WS 会话存储;replayCollector 增加 allItems/Complete 认证(终端 output 数组为权威顺序,item 事件后终端为空不认证完整);prepareOpenAIWSHTTPBridgeBody 对 Codex 协议/Grok 账号携带 previous_response_id 的桥接请求 fail-closed(不允许通过删除锚点伪造无状态重放);400+ 循环支持 rejected-field 重试(带状态上限);首轮语义输出前 staged 缓冲(openAIFirstOutputStageMaxBytes 上限)配合 Cindy 余额检测(输出前换号、输出后只发 sanitize 重试事件并保留 usage 返回 resultWithUsage);官方 OpenAI 裸 error 事件挂起合成 response.failed(后续 completed 到达则撤销);容量降载码只改写客户端副本;Grok 缓存身份/工具路由/内容策略与 Cindy model_not_supported 均委托对应助手(grok_*、cindy_*、apicompat)。桥接机制归 core。静态阅读。", - "evidence": [ - "Full-file static review in 3 chunks: artifacts/evidence/v027-claude-S12-svc-openai-ws-1-review.json", - "Anchors: openAIWSHTTPBridgeTurnState L34-39 with applyBridgeOwnedTurnState L563-574, prepareOpenAIWSHTTPBridgeBody anchor fail-closed L261-267, replay collector completeness L281-338, rejected-field retry loop L609-647, first-output staging + Cindy balance ordering L817-841/L972-1026, bare-error synthesis finalizeBareError L746-777, capacity-shed client copy sanitize L962-971, terminal handling L1031-1055.", - "Boundary: no session/store writes from bridge turns except the caller-owned bridgeState; response bindings are done by the ingress caller.", - "Static read only; no execution." - ] - }, - { - "path": "backend/internal/service/openai_ws_http_bridge_isolation_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b747938dbef1d494ade2c1fc9562f6fb732ab371d5f52b2e533505be8bcd6e0e", - "review_fingerprint": "b747938dbef1d494ade2c1fc9562f6fb732ab371d5f52b2e533505be8bcd6e0e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "WS HTTP bridge 会话隔离测试(354 行全读)。下游相对上游把 BindSessionTurnState/GetSessionTurnState 改为带 account.ID 的账号隔离形态,注入不可信客户端 turn-state 头并断言其不上行,新增 openaiCodexTurnStateOrigins 共享溯源不发布断言,以及整个新测试 TestOpenAIWSHTTPBridgeClearsOwnedStateWhenResponseOmitsHeader:三轮桥接中响应缺失 turn-state 头时清空桥接自有状态、且不触碰 native store 哨兵。证明核心网关桥接的账号绑定与状态清理修复,非插件业务。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "Delta vs aea725f: L158 injects openAIWSTurnStateHeader 'untrusted-client-turn-state'; L163/L244 add account.ID arg; L250-L253 provenance assertions; L255-L354 new owned-state-clear test asserting upstream requests carry ['', 'state-from-first-turn', ''] and native sentinels survive.", - "Call chain: exercises svc.ProxyResponsesWebSocketFromClient + BeginOpenAIWSIngressSessionPreemption against httptest WS server with httpBridgeIsolationUpstream stub; state store from NewOpenAIWSStateStore(nil).", - "No production behavior edit; assertions read statically, not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_http_bridge_resume_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d693565c0abb0616b2bbcc9b3fa8e354fad90a30a4c861127b84c5b00a6d115e", - "review_fingerprint": "d693565c0abb0616b2bbcc9b3fa8e354fad90a30a4c861127b84c5b00a6d115e", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "桥接 429 当前轮跨账号重试测试(263 行全读)。下游相对上游只做两处签名适配:buildOpenAIWSCurrentTurnRetryPayload 新增 verified 布尔(重放需完整基线证明,孤儿 tool output 拒绝重试),scopeCodexAccountIdentityValue 去掉 kind 参数(session/thread 统一按账号+槽位缩放 client_metadata);并把 429 预写失败夹具改为不带 previous_response_id。断言仍证明:失败前零下游写、替换账号重放完整 input、turn-state 头不带到新账号。核心协议 failover 行为的证明,静态阅读未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "Delta vs aea725f: L27 buildOpenAIWSCurrentTurnRetryPayload(payload, fullInput, true, true, model) gains verified flag; L256-L261 scopeCodexAccountIdentityValue(account, 0, value) drops the 'session'/'thread' kind argument; L47 fixture drops previous_response_id.", - "Assertions: L63 zero writes before failover; L232-L243 retry payload strips previous_response_id, keeps 4 input items and client_metadata; L262 replacement account request has empty openAIWSTurnStateHeader.", - "No production behavior edit; test not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_http_bridge_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "55ad5af7a4ace19655f6bdb6125dda4c97f322eaecc670f3a7b6290bda5394df", - "review_fingerprint": "55ad5af7a4ace19655f6bdb6125dda4c97f322eaecc670f3a7b6290bda5394df", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "WS→HTTP bridge 主测试集(2271 行全读,31 个测试)。下游相对上游的行为改变并由断言证明:prepareOpenAIWSHTTPBridgeBody 保留 previous_response_id 原生锚点与显式 reasoning.effort:none(上游版本会剥离);续轮只发增量 input 而非重放全史;rejected-field 精确重试按 openAIWSHTTPBridgeTurnState{accountID,value} 只保留同账号已证明的 turn-state,不回放不可信客户端头;新增 Cindy 余额失败写序测试(budget_exceeded 与上游敏感信息不落客户端、markCalls 等独立确认);API key 失败不再持久化旧版账号错误状态,改用进程内 runtime block。主体是核心桥接转发/failover 协议;Cindy 用例测的是核心 bridge 对该错误形态的脱敏与写序,余额语义本身在 cindy-provider。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "Delta vs aea725f: L33-L46 renamed test now asserts previous_response_id preserved (was require.False upstream); L48-L61 reasoning.effort none preserved; L873-L939 ownership-parameterized rejected-field retry via openAIWSHTTPBridgeTurnState; L979-L1049 new TestProxyOpenAIWSHTTPBridgeTurnCindyBalanceWriteOrdering; L1142-L1143 setErrorCalls zero + isOpenAIAccountRuntimeBlocked; L2157-L2166 continuation keeps anchor with single-item input.", - "Call chain: proxyOpenAIWSHTTPBridgeTurn / ProxyResponsesWebSocketFromClient / shouldBridgeOpenAIWSHTTP / shouldBridgeOpenAIWSPassthroughFirstMessage against httpUpstreamRecorder stubs; capacity-shed rewrite (server_is_overloaded -> server_error) at L1054-L1111.", - "Not claimed: no execution of the suite, no production or network verification." - ] - }, - { - "path": "backend/internal/service/openai_ws_protocol_forward_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8c395ae190adc0aa10b51cee4a1c4e0bec632c73494791bcf6b8e8203f1f91aa", - "review_fingerprint": "8c395ae190adc0aa10b51cee4a1c4e0bec632c73494791bcf6b8e8203f1f91aa", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "Forward 入口 WS/HTTP 协议选择与 continuation 状态错误测试(1901 行全读)。下游的核心行为反转并被断言证明:上游允许的自动恢复(previous_response_not_found 时去掉引用重试、invalid_encrypted_content 时删密文重试一次)在下游一律改为终态 UpstreamFailoverError.IsOpenAIContinuationStateUnavailable —— 不删除客户端续接状态、只打一次上游、不回退 HTTP、不换账号重试、SuppressAccountHealthPenalty、且 c.Writer 不伪造成功交由 handler 输出标准终态;HTTP 入站在 OpenAIReasoningSignatureRecoveryEnabledExtraKey=false 时同样终态。WS 拨号 426/重试上限/策略违规等既有用例保留。核心网关协议正确性修复的证明。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "Delta vs aea725f: TestOpenAIGatewayService_Forward_WSv2PreviousResponseNotFound* now require wsAttempts==1 and Len(requests,1) keeping previous_response_id (was 2 attempts with the reference stripped upstream); same inversion for WSv2InvalidEncryptedContent* (L1458-L1577, L1680-L1799) and HTTP ingress variants (L191-L361) gated by OpenAIReasoningSignatureRecoveryEnabledExtraKey:false.", - "Common assertions: failoverErr.IsOpenAIContinuationStateUnavailable, ShouldRetryNextAccount false, SuppressAccountHealthPenalty true, upstream.lastReq nil (no HTTP fallback), c.Writer.Written() false.", - "Test read statically; no execution." - ] - }, - { - "path": "backend/internal/service/openai_ws_ratelimit_signal_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4f6f5519d4e584a2fd044453479e5423277e7cf5928e3bd3274a69ff1c5bfc5e", - "review_fingerprint": "4f6f5519d4e584a2fd044453479e5423277e7cf5928e3bd3274a69ff1c5bfc5e", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static test source exercises OpenAI WS/header and usage snapshot signals, including non-exhausted and exhausted paths; test execution was not repeated.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=4f6f5519d4e584a2fd044453479e5423277e7cf5928e3bd3274a69ff1c5bfc5e; current_sha256=4f6f5519d4e584a2fd044453479e5423277e7cf5928e3bd3274a69ff1c5bfc5e; inventory_sha256_match=true", - "TestOpenAIGatewayService_UpdateCodexUsageSnapshot_ExhaustedSnapshotDoesNotSetRateLimit", - "TestOpenAIGatewayService_UpdateCodexUsageSnapshot_NonExhaustedSnapshotDoesNotSetRateLimit", - "TestOpenAIGatewayService_GetSchedulableAccount_ExhaustedCodexExtraDoesNotSetRateLimit" - ] - }, - { - "path": "backend/internal/service/openai_ws_reasoning_mode_model_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "01ccf05583a4bfc456e04d4bf4d900a65b3096d4b34f3102e07cf3cb3872c584", - "review_fingerprint": "01ccf05583a4bfc456e04d4bf4d900a65b3096d4b34f3102e07cf3cb3872c584", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增下游测试(188 行全读,上游无此文件)。证明 WS ingress 的 reasoning 归一化以解析后的会话模型为键而非客户端别名:账号 model_mapping 把别名解析到 gpt-6-astra 时保留 reasoning.mode=pro,解析到非 astra 模型时转换为 reasoning.effort=max;MapRequestModel 每轮恰好调用一次且第二轮继承会话模型;passthrough selected 兼容模式对已签名历史逐字节保留(不重序列化 raw、保留大数与 1.2300 精度),OAuth/SetupToken 丢弃孤儿 function_call_output 而普通 API key 保持 3 项不动。归一化实现在核心 openai_gateway_request_body.go(normalizeOpenAIResponsesReasoningModeForModel),未见插件重复执行体。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "New downstream file (git ls-tree aea725f prints nothing); whole file is the delta.", - "Anchors: L26-L29 case table astra->mode pro / non-astra->effort max; L100 mappedClientModels exactly once per turn; L168 'selected compatibility must not reserialize raw signed history'; L171-L173 orphan output kept only for AccountTypeAPIKey.", - "Call chain: startPassthroughLifecycleServerWithHooks -> ProxyResponsesWebSocketFromClient -> openai_ws_v2_passthrough_adapter; normalization owned by core (rg: normalizeOpenAIResponsesReasoningModeForModel in openai_gateway_request_body.go:1186). Test not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_state_fidelity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7ca0241325413cde4b56d5c22874e35bf0c4ab433c942cde4336252fa987148c", - "review_fingerprint": "7ca0241325413cde4b56d5c22874e35bf0c4ab433c942cde4336252fa987148c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增下游测试(160 行全读,上游无此文件)。证明重放/重试的状态保真规则:openAIWSReplayHistoryVerified 仅在全新完整输入或与已验证完整基线匹配时为真(外部基线、conversation 引用、item_reference、孤儿 tool output 一律拒绝);prepareOpenAIWSVerifiedReplayPayload 不改原请求、保留全部扩展字段与顺序;buildOpenAIWSCurrentTurnRetryPayload 必须有 verified 证明否则返回 nil(tool 配对本身不构成跨账号可移植性);openAIWSToolCallReplayCollector 以成功终态的 output 顺序为权威、不一致终态不判 Complete;HTTP bridge 的 encrypted/anchor 状态错误为终态且零客户端写、请求体不被变造。这组断言是 S13 内多处 verified 参数签名变更的语义来源。核心协议正确性证明,静态阅读未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "New downstream file (no upstream blob); whole file is the delta.", - "Anchors: L18-L39 baseline truth table; L52-L70 verified replay preserves order/extensions and portable retry still nil; L94-L126 terminal-order collector incl. 'inconsistent terminal must not delete observed output'; L128-L159 bridge state errors terminal, writes==0, body JSONEq original.", - "Call chain: helpers buildOpenAIWSCurrentTurnRetryPayload / prepareOpenAIWSVerifiedReplayPayload / openAIWSToolCallReplayCollector live in the openai_ws_forwarder_support / http_bridge paths. Test not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_state_store.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "b800e6961bb8277f92b2b61cc471199e8763d0e4809fec9b0c65dd0e29a9ca84", - "review_fingerprint": "b800e6961bb8277f92b2b61cc471199e8763d0e4809fec9b0c65dd0e29a9ca84", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "WSv2 粘连状态存储(764 行全读,本地 map+Redis 双层:response->account/conn、session->turnState/conn、invalid_encrypted lineage)。下游相对上游的修复:turn-state 绑定强制携带 accountID(openAIWSTurnStateBinding 增加 accountID,Get 按账号过滤),封堵跨账号读到他人 turn-state;新增 DeleteResponseAccountIfMatches 双层 CAS 删除防止清理误删并发重绑;新增 LookupOpenAIContinuationBinding 三态(hit/miss/store_error),GetResponseAccount/GetHTTPResponseOwner 区分 ErrStickySessionNotFound 与真实存储错误(上游把所有错误降级为 miss)。内存有界:65536/map 上限任意淘汰 + 每分钟增量清理 512/map。属于留在 core 的通用机制,delta 为正确性修复;见 findings 的 variadic API 低危问题。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "Delta vs aea725f: L41-L45 accountID field; L392-L449 variadic Bind/Get with account filter (L445 binding.accountID != accountID -> miss); L313-L345 DeleteResponseAccountIfMatches local+redis CAS; L100-L126 LookupOpenAIContinuationBinding; L281-L291 store errors now propagate instead of degrading to miss.", - "Call chain: production binders/readers all pass account.ID (openai_codex_turn_state.go:147, openai_ws_forwarder_ingress.go:721, openai_ws_forwarder_v2.go:176); CAS delete used by openai_ws_forwarder_support.go:849,860; lookup also by openai_cindy_opaque_binding.go:134.", - "Bounded maps verified: ensureBindingCapacity L711-L723 + incremental cleanup L576-L613. No test execution." - ] - }, - { - "path": "backend/internal/service/openai_ws_state_store_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "efc2065761af9b1562b060dbdd36fcf3fb9ab4d6d53cacea83dacf0382c17fbf", - "review_fingerprint": "efc2065761af9b1562b060dbdd36fcf3fb9ab4d6d53cacea83dacf0382c17fbf", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "状态存储单测(315 行全读)。下游新增/改动的断言证明上述修复:DeleteResponseAccountIfMatches 不删并发重绑的新绑定、匹配时两层都删;SessionTurnState 增加账号隔离断言(同组同 hash 不同 accountID 不命中);LookupOpenAIContinuationBinding 区分 miss(含 ErrStickySessionNotFound 哨兵)与 store_error;Redis 操作独立 3s 超时探针;增量清理与容量淘汰行为。注意下游删除了上游的 TestOpenAIWSStateStore_HTTPResponseOwnerPersistsAcrossStoreInstances(跨实例 Redis 持久化用例被 CAS 用例替换),owner 机制本身未变。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "Delta vs aea725f: L31-L55 new CAS-rebind test; L70-L89 account isolation assertions (L83 GetSessionTurnState(9, hash, 202) false); L285-L307 new LookupOpenAIContinuationBinding tri-state test; probe cache gains getErr + DeleteSessionAccountIDIfMatches stub.", - "Coverage note: upstream cross-instance HTTPResponseOwner persistence test was removed in the same hunk that added the CAS test.", - "Test read statically; not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_v2_passthrough_adapter.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "7e34613c95c8099efc11c251d325560385a85887194670a73b2c6e097887f9fd", - "review_fingerprint": "7e34613c95c8099efc11c251d325560385a85887194670a73b2c6e097887f9fd", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "OpenAI Responses WS v2 passthrough relay 适配器(1935 行全读;FROZEN,审的是 post-63a98c8cc 的当前磁盘字节,sha 7e34613c…,与切片 28b1b577… 不同,按 Codex 冻结指示记录新 sha)。它是 host 侧把客户端 WS 帧中继到上游 WS 的胶水:鉴权、fast policy、账号身份 client_metadata 缩放、Codex 指纹、request-integrity 快照,本身不拥有业务规则。下游相对上游新增:一次同账号 transport 重试外层循环(errOpenAIWSPassthroughRetrySameAccount + openAIWSInitialDialFailover)、legacy Laxa/Cindy 模型线映射(resolveLegacyCindyOpenAIModelContext / replaceLegacyCindyWSPassthroughSessionModelContext,仅 IsLegacyCindyAPIKeyAccount 生效)、Cindy 余额终态 failover 的 replay-safe 判定与 refusal-recovery 缓冲、continuation 状态错误终态化、legacy Laxa 响应锚点账号亲和绑定。这些桥接 cindy-provider 能力,故 decision=adapter、owner=cindy-provider(模型/定价/余额语义属该域)。见 findings 的工具名还原不对称低危项。静态阅读,未执行、未联网。", - "evidence": [ - "Full-file static review at current on-disk bytes: sha256 7e34613c95c8099efc11c251d325560385a85887194670a73b2c6e097887f9fd (recomputed read-only; slice was 28b1b577..., changed after 63a98c8cc and now FROZEN per Codex).", - "Delta vs aea725f: L716-L745 proxyResponsesWebSocketV2Passthrough splits into retry wrapper + Attempt(transportRetryUsed); L112-L152 resolveLegacyCindyOpenAIModelContext/replaceLegacyCindyWSPassthroughSessionModelContext (sjson); L1031-L1044 openAIWSInitialDialFailover same-account retry; L1360-L1377 refusal/strict-cindy buffered output; L1532-L1560 cindyBalanceTerminalFailover replay-safe + continuation-state terminal.", - "Adapter boundary: model resolution delegates to resolveOpenAIForwardModelContext/normalizeOpenAIModelForUpstream and cindyLegacyLaxaLiveUpstreamModel; fast policy via applyOpenAIFastPolicyToWSResponseCreate; relay via openaiwsv2.RunEntry. Account affinity persisted via getOpenAIWSStateStore().BindResponseAccount only for IsLegacyCindyAPIKeyAccount (L1475-L1483).", - "Not claimed: no execution, no upstream WS dial, no network or model API call; behavior asserted only by the sibling lifecycle/effort tests reviewed in this slice." - ] - }, - { - "path": "backend/internal/service/openai_ws_v2_passthrough_adapter_effort_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c01ca8068d510f4aec9a23201fef0b0bb3b838707cd40d8ad9eb48e191a1ea67", - "review_fingerprint": "c01ca8068d510f4aec9a23201fef0b0bb3b838707cd40d8ad9eb48e191a1ea67", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "passthrough usage-meta reasoning-effort 单测(46 行全读,//go:build unit)。下游相对上游把 TestWSPassthroughUsageMeta_InitFromFirstFrame_NonGPT56FallsBackToXHigh 改名并反转断言为 PreservesExplicitMax:usage metadata 现在如实保留出站 effort=max(不再对非 5.6 模型把 max 归一为 xhigh),同时 requestedReasoningEffort 保留 mapping 前的原值。测的是 passthrough 适配器的 usage 记账辅助(openAIWSPassthroughUsageMeta),归属随适配器到 cindy-provider(effort/model 语义域)。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S13-svc-openai-ws-2-review.json", - "Delta vs aea725f: L22 test renamed InitFromFirstFrame_NonGPT56FallsBackToXHigh -> PreservesExplicitMax; L31 assertion 'xhigh'/normalize -> 'max'/'usage metadata preserves the actual outbound effort'.", - "Subject: newOpenAIWSPassthroughUsageMeta / initFromFirstFrame / updateFromResponseCreate / captureRequestedReasoningEffort in openai_ws_v2_passthrough_adapter.go L186-L263.", - "Test read statically; not executed." - ] - }, - { - "path": "backend/internal/service/openai_ws_v2_passthrough_lifecycle_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ed7c3da39694a370b9ecbfbe1555d431d68d5714566bfded38f562888de7cd72", - "review_fingerprint": "ed7c3da39694a370b9ecbfbe1555d431d68d5714566bfded38f562888de7cd72", - "review_status": "pending" - }, - { - "path": "backend/internal/service/ops_concurrency.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d727bcbf750cc95017f9bfc7770cf57c1cf1bc85af57b6f49e469b86421bd1f2", - "review_fingerprint": "d727bcbf750cc95017f9bfc7770cf57c1cf1bc85af57b6f49e469b86421bd1f2", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "Ops 实时并发统计(按平台/组/账号聚合)。下游唯一改动:getAccountsLoadMapBestEffort 去重时改用 acc.Concurrency 作为 AccountWithConcurrency.MaxConcurrency,替换原来的 acc.EffectiveLoadFactor()——与同文件用户侧 getUsersLoadMapBestEffort(用 u.Concurrency)对齐,字段名即 MaxConcurrency,属把负载权重误当容量的纠正。分类为 core-correctness、宿主 Ops 观测机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: only the dedup key changed (comment + EffectiveLoadFactor()->Concurrency at getAccountsLoadMapBestEffort ~L69-79).", - "Sibling getUsersLoadMapBestEffort already uses u.Concurrency for MaxConcurrency; batch consumer concurrencyService.GetAccountsLoadBatch expects real capacity.", - "Bounded paging (page>10000 abort), best-effort zeroing on batch error; no correctness/security issue introduced.", - "OpsService observability backend stays in core; plugins/admin-observability provides only UI + policy (no reference to OpsService)." - ] - }, - { - "path": "backend/internal/service/ops_log_runtime_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7e78460b5a03fb70120affb5ef9216c4424a86fdfd1b3d1c5f1bf7ca81bebc1e", - "review_fingerprint": "7e78460b5a03fb70120affb5ef9216c4424a86fdfd1b3d1c5f1bf7ca81bebc1e", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "OpsService 运行时日志配置单测(更新/校验/归一化/重置回落基线/持久化失败回滚/启动应用)。下游改动仅在 TestResetRuntimeLogConfig_InvalidOperator 的 nil 守卫后加一行 return(t.Fatal 后的静态 nil 安全强化,运行时无行为变化)。被测主体是 core Ops 运行时日志机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: single '+return' after t.Fatalf in a nil/err guard (L236).", - "Covers UpdateRuntimeLogConfig invalid-config no-apply, persist-failure rollback of level + persistAccessLogs, ResetRuntimeLogConfig baseline fallback + key delete, validate/normalize defaults.", - "t.Fatal calls runtime.Goexit so the added return is a no-op at runtime; lint/nil-analysis hardening only.", - "Subject is core OpsService (settingRepo/systemLogSink/cleanupReloader)." - ] - }, - { - "path": "backend/internal/service/ops_metrics_collector.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "bf6844f4ecee0662db4521a2a71411cc2f90cefe9faee6d35d50498aedbefa1b", - "review_fingerprint": "bf6844f4ecee0662db4521a2a71411cc2f90cefe9faee6d35d50498aedbefa1b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主 Ops 指标采集器(系统 CPU/内存 cgroup 优先、DB/Redis 池、用量/延迟/错误 SQL 聚合、并发队列深度、Redis 领导锁+DB advisory 回退)。下游两处改动:新增 DB 连接池等待增量指标 recordDBPoolStats(带基线重置检测与 int 溢出上限)与 DBConnWaiting;以及 listSchedulableAccountLoads 的 MaxConcurrency 改用 account.Concurrency(同 ops_concurrency.go 的容量纠正)。generic 宿主观测机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: +dbPoolStatsMu/lastDBWaitCount/hasDBWaitSample fields, dbPoolStats now returns waiting, new recordDBPoolStats (reset when WaitCountaccount.Concurrency.", - "All SQL is parameterized ($1/$2); queryErrorCounts filters is_count_tokens=FALSE; account-switch count via jsonb_array_elements.", - "collectConcurrencyQueueDepth uses ListSchedulableAccountLoads projection when repo implements it, else falls back to ListSchedulable; bounded 2s timeouts.", - "Observability collector stays in core (admin-observability plugin has no backend reference)." - ] - }, - { - "path": "backend/internal/service/ops_metrics_collector_projection_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a48c73e22d3bd4a6564284e7ab48ac0ca4531e22b694784097dc28bedb5be90a", - "review_fingerprint": "a48c73e22d3bd4a6564284e7ab48ac0ca4531e22b694784097dc28bedb5be90a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "collectConcurrencyQueueDepth 的投影路径单测。下游改动把 fixture 与 benchmark 的 AccountWithConcurrency.MaxConcurrency 从 loadFactor 改为账号真实 Concurrency,正是 ops_concurrency.go/ops_metrics_collector.go 容量纠正在测试侧的印证;断言投影仓库(ListSchedulableAccountLoads)与回退(ListSchedulable)结果一致、缓存收到的批次相同。core Ops 观测。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: fixture {11:7->2,13:1->0} and benchmark MaxConcurrency:loadFactor->accounts[i].Concurrency.", - "Asserts projectionCalls==1 & listCalls==0 for projection repo, fallback listCalls==1, identical queue depth (5) and identical cache.got batches.", - "Corroborates the MaxConcurrency=Concurrency correctness change; not executed.", - "Subject is core OpsMetricsCollector." - ] - }, - { - "path": "backend/internal/service/ops_metrics_collector_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6a1734895f2bd21b7b5594610183191708dc3368b1ae9bad84c21c6e8889e774", - "review_fingerprint": "6a1734895f2bd21b7b5594610183191708dc3368b1ae9bad84c21c6e8889e774", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "OpsMetricsCollector 单测。下游新增 TestOpsMetricsCollectorQueryErrorCountsExcludesCountTokens(+16 行)用 sqlmock 断言 queryErrorCounts 的 SQL 含 AND is_count_tokens = FALSE 且六个计数列正确;文件另有 DB 池等待增量基线/重置断言与 fast-policy 阻断响应标记。core Ops 观测 SQL 正确性。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: +16 lines adding the count-tokens-exclusion sqlmock test.", - "TestOpsMetricsCollectorRecordsDatabasePoolWaitDelta proves cumulative-wait baseline + reset on pool replacement; TestWriteOpenAIFastPolicyBlockedResponseMarksBusinessLimited proves 403 + business-limited reason.", - "sqlmock regex asserts FROM ops_error_logs ... AND is_count_tokens = FALSE.", - "Subject core; test read statically, not executed." - ] - }, - { - "path": "backend/internal/service/ops_queue_sanitize_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3506535a6e0db83da56808569518308578f444f3484216f04995e28d6bdee7b9", - "review_fingerprint": "3506535a6e0db83da56808569518308578f444f3484216f04995e28d6bdee7b9", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "SanitizeOpsUpstreamErrorsForQueue 的安全/健壮性单测:字段长度上限、凭据(Bearer/api_key)脱敏、事件数硬上限(256)与序列化字节预算(512KB)、最旧保留事件记录丢弃计数、纯空事件丢弃、忽略调用方伪造的 DroppedEarlierAttempts。下游改动仅在一处 nil 守卫加 return(t.Fatal 后静态安全,无行为变化)。被测主体 core Ops 队列净化。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: single '+return' after t.Fatal (L30 guard).", - "Proves redaction of 'Bearer secret'/'api_key', bounds on Platform/AccountName/UpstreamURL/Message, newest-wins retention + dropped_earlier_attempts stamping, byte-budget dropping.", - "Tests constants opsUpstreamErrorsMaxEvents/QueueMaxBytes and helper boundOpsUpstreamErrors from ops_service.go.", - "Subject core; delta is lint hardening only." - ] - }, - { - "path": "backend/internal/service/ops_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a04b985331cfb7f9702bbc2251b5cdad13efe42c0c255a1e75455cd3f0f40e6b", - "review_fingerprint": "a04b985331cfb7f9702bbc2251b5cdad13efe42c0c255a1e75455cd3f0f40e6b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主 Ops 监控服务:运行时设置原子快照与后台刷新、错误日志摄取(RecordError/Batch)、上游错误净化(脱敏白/黑名单、JSON 修剪、字节/事件上限)、用户侧错误查询(强制按 user_id 归属、View=all、排除 count_tokens)与详情越权返回 NotFound。下游改动:结构体新增 quotaActivity 字段(见 findings,当前未被读取,dead)与在 sanitizeOpsUpstreamErrors 中对保留 body 的事件调用 sanitizeOpenAIContinuationDiagnostic 写入 ContinuationDiagnostic。generic 宿主机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (1138 lines). git diff aea725f: +quotaActivity field (L46) and continuation-diagnostic sanitize block in sanitizeOpsUpstreamErrors (~L593-598).", - "GetUserErrorRequestDetail enforces ownedDirectly (detail.UserID==userID) else NotFound; ListUserErrorRequests shallow-copies filter and forces UserID/View/ExcludeCountTokens (no IDOR).", - "isSensitiveKey redaction whitelists token-count fields, blacklists credentials by exact/suffix/substring; boundOpsUpstreamErrors keeps newest attempt within 512KB budget.", - "FINDING: quotaActivity assigned by wire.go:881 but never read by any OpsService method (dead injected dependency)." - ] - }, - { - "path": "backend/internal/service/ops_service_user_error_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a7e2785d670cbc4a98a1ba242d35ed46e808f3da46e85413dd1e2bb4d784f9cd", - "review_fingerprint": "a7e2785d670cbc4a98a1ba242d35ed46e808f3da46e85413dd1e2bb4d784f9cd", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "OpsService 用户侧错误接口单测:ListUserErrorRequests 强制按调用者 user_id、View=all、ExcludeCountTokens、清空 Phase、透传 APIKeyID 且不原地篡改调用方 filter;GetUserErrorRequestDetail 越权(caller!=owner)返回 NotFound、合法返回详情、无效 id 报错。安全相关(IDOR/归属)。下游改动仅一处 nil 守卫加 return(无行为变化)。被测主体 core Ops。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: single '+return' after t.Fatal at legitimate-access guard (L121).", - "Proves forced-scope + shallow-copy isolation and NotFound-on-cross-user ownership enforcement.", - "Uses stubOpsRepoForUserErr embedding OpsRepository; asserts NotFound via infraerrors.IsNotFound.", - "Subject core OpsService; delta is lint hardening only." - ] - }, - { - "path": "backend/internal/service/ops_system_log_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8997c7c1ed561d3a9b3c158abf52ad23416d3789ce508008898ec155c2dc875e", - "review_fingerprint": "8997c7c1ed561d3a9b3c158abf52ad23416d3789ce508008898ec155c2dc875e", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "OpsService 系统日志单测:ListSystemLogs 默认分页 clamp(page=1,size=200)、监控关闭报错、nil repo 返回空、repo 错误映射 OPS_SYSTEM_LOG_LIST_FAILED;CleanupSystemLogs 审计条件序列化(含 host/client_request_id/user_id/api_key_id)、算子校验、需要过滤条件、无效时间区间、无行短路、审计失败不阻断;sink 健康。下游改动仅四处 nil 守卫加 return(无行为变化)。被测主体 core Ops。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: 4x '+return' after t.Fatalf in nil/err guards (L35,L78,L119,L156).", - "NewOpsService called with 11 positional args (matches constructor); opsRepoMock drives List/Delete/InsertSystemLogCleanupAudit.", - "marshalSystemLogCleanupConditions asserted for nil ({}) and populated JSON.", - "Subject core OpsService; delta is lint hardening only." - ] - }, - { - "path": "backend/internal/service/ops_upstream_context.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3f3c8fb061b5dd701e86059d9c76e039670573a9e2667b74ecc3debc22c69181", - "review_fingerprint": "3f3c8fb061b5dd701e86059d9c76e039670573a9e2667b74ecc3debc22c69181", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主 Ops 错误日志的 gin 上下文契约与辅助:上游状态/消息/明细/事件的 context key、就地 SSE 流内错误(首个生效去重、按 WS turn 作用域)、business-limited 标记、代理归因不可变且无凭据、upstream_errors JSON 归一化、safeUpstreamURL 剥离 query/fragment 防泄露。下游唯一改动:OpsUpstreamErrorEvent 新增 ContinuationDiagnostic 字段(有界、无内容、omitempty,注释明确禁止用于透传规则或重试判断)。generic 宿主机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (682 lines). git diff aea725f: +ContinuationDiagnostic *OpenAIContinuationDiagnostic on OpsUpstreamErrorEvent (~L425-427).", - "safeUpstreamURL strips ?/# to avoid OAuth-token leakage; proxy attribution invariant (proxy_id==null => sentinel name) enforced by normalizeOpsUpstreamProxyAttribution.", - "The diagnostic type/sanitizer live in openai_continuation_diagnostic.go (other slice) with dedicated privacy + resource-bounds tests; sanitize is applied on the queue path in ops_service.go.", - "SkipMonitoring stays json:\"-\" (request-local, not persisted)." - ] - }, - { - "path": "backend/internal/service/ops_user_error_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "05d2d915b767d59e5ed8cf624e7246a0f7d50edc50c96de6d72db41aab1d0943", - "review_fingerprint": "05d2d915b767d59e5ed8cf624e7246a0f7d50edc50c96de6d72db41aab1d0943", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "用户侧错误映射/脱敏单测:MapUserErrorCategory 与 CategoryToFilter 的相位/类型映射、ToUserErrorRequest 字段映射、ToUserErrorRequestDetail 白名单化并断言 JSON 中不含 user_email/upstream_endpoint 敏感字段。下游改动仅一处 nil 守卫加 return(无行为变化)。被测主体 core Ops 脱敏。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: single '+return' after t.Fatal at L134 detail guard.", - "TestToUserErrorRequestDetail_WhitelistAndRedacts marshals output and asserts user_email/upstream_endpoint are absent while client_ip/user_agent/group_name/stream are intentionally exposed.", - "Category mapping table covers auth/rate_limit/quota/invalid_request/service_unavailable/upstream/internal/other.", - "Subject core; delta is lint hardening only." - ] - }, - { - "path": "backend/internal/service/payment_order_result_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "42dc5e4ad7923ca8f3bacae6a70833dd270d5d202705689bc0ff055576123b09", - "review_fingerprint": "42dc5e4ad7923ca8f3bacae6a70833dd270d5d202705689bc0ff055576123b09", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "PaymentService 下单辅助函数单测:Alipay 手机预下单开关、官方支付宝识别、buildCreateOrderResponse(order_created vs jsapi 别名)、支付详情去除 NUL 字节但不动 client_secret、货币精度(JPY/KWD 零小数拒绝)、CNY 订阅 opt-in 汇率换算与手续费顺序、充值倍率、有效期单位、商品名前后缀、微信 OAuth-required(需 MP 配置/resume 签名密钥、旧签名密钥兼容回退、easypay 跳过)。下游改动仅三处 nil 守卫后加 return(无行为变化)。被测主体 core 支付。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: 3x '+return' after t.Fatal in nil guards (resp/OAuth at L391,L505 area).", - "Proves currency-precision INVALID_AMOUNT gating, subscription CNY conversion is opt-in (rate=0 keeps direct price), NUL-sanitization scope excludes client_secret.", - "WeChat OAuth path requires MP config + PAYMENT_RESUME_SIGNING_KEY, falls back to configured legacy key, skips EasyPay provider.", - "Subject core payments; delta is lint hardening only, test not executed." - ] - }, - { - "path": "backend/internal/service/plugin_account_create.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "3663277e8bd1c5e3b2cc377f7a2484b283e103ff5593244787d5f2e61ecd7431", - "review_fingerprint": "3663277e8bd1c5e3b2cc377f7a2484b283e103ff5593244787d5f2e61ecd7431", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文439行:host验证有限创建声明、唯一注册owner及精确归一端点;ID-less创建只接受同owner Provider/Admin完整范围交集,不借账号0灰度。运行/依赖/配置和包/定义/代次均重验,输入拷贝后绑定独立host策略lease,保留原job主owner;事务结束才释放且提交前复核。默认只用于批准创建目标,显式值保留;设备来源先验证再由host派生,合法存量导入model_mapping不被UI provider_managed误禁。固定错误不泄漏凭据。该结论不覆盖后续Edit/Duplicate迁移或真实进程运行。", - "evidence": [ - "artifacts/evidence/v027-account-create-integration-review.json#verification", - "artifacts/evidence/v027-astra-account-create-backend-review.json" - ] - }, - { - "path": "backend/internal/service/plugin_account_create_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "994e24b12c861a68f4416cf4d5512fa90f22045e337e83ca5b790b05af8e83cb", - "review_fingerprint": "994e24b12c861a68f4416cf4d5512fa90f22045e337e83ca5b790b05af8e83cb", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "全文362行:fixture读取真实Cindy声明并调用实际manager/中央Create,覆盖双100%与新鲜版本、默认组回退/空组拒绝、显式zero/null/auto、普通OpenAI+Laxa独立、非法provenance及合法导入映射、host输入/来源、同owner多策略fence和外层事务lease。sqlmock仅证明生命周期hook,不冒充数据库锁;合成全局invoker在cleanup恢复。复用报告中的实际绿方法与两个兼容反例red→green,不重复执行。", - "evidence": [ - "artifacts/evidence/v027-account-create-integration-review.json#verification", - "artifacts/evidence/v027-astra-account-create-backend-review.json" - ] - }, - { - "path": "backend/internal/service/plugin_account_edit.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "638c5065da9d32c217681275baa526384e4543ec9695832a2aa00347c65ab562", - "review_fingerprint": "638c5065da9d32c217681275baa526384e4543ec9695832a2aa00347c65ab562", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_account_edit_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2223906cbb423da3d99b6d6133bc153aaa18eabf05873e027d5c2e675c6cb7b9", - "review_fingerprint": "2223906cbb423da3d99b6d6133bc153aaa18eabf05873e027d5c2e675c6cb7b9", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_account_import.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "622440ed147f2316436d32a4571ce2743a57c07bf641200d653436832639cfe5", - "review_fingerprint": "622440ed147f2316436d32a4571ce2743a57c07bf641200d653436832639cfe5", - "review_status": "reviewed", - "decision": "adapter", - "owner": "account-tools", - "reason": "Host import adaptation exposes bounded immutable identity/target facts, never credentials, to the plugin. It validates exact source indexes and allowed account/group targets, computes cross-chunk tracking from early-rejection eligibility rather than plugin flags, rejects forged executable duplicate/device/invalid-target plans, and leaves create/update/reject decisions and business error priority in the plugin. Unavailable policy has no legacy executor fallback.", - "evidence": [ - "prepare/finalize chunk planning and merge validate request identity, tracking and final non-execution safety against host facts; Matches ambiguity remains tracked while API/target/payload/device/source early rejects do not.", - "v027-astra-import-integrity-review.json: current-source inspection and six actual host tests, including a previously failing device-conflict priority case and 1001/1005-item cross-chunk mutations." - ] - }, - { - "path": "backend/internal/service/plugin_account_import_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "10a8ce68f200e4465b5c0039063148f5d92c33a52447bb4e6afa2b0c5c01d697", - "review_fingerprint": "10a8ce68f200e4465b5c0039063148f5d92c33a52447bb4e6afa2b0c5c01d697", - "review_status": "reviewed", - "decision": "reference", - "owner": "account-tools", - "reason": "The fixture runs the real account-tools policy in process and records bounded RPC payloads. Assertions cover allowed account/group identities, disabled-policy rejection, 1002-item cross-chunk duplicates, forged prepare/finalize tracking, valid counterparts of five early rejects, retained DeviceConflict priority, and forged executable duplicates or invalid targets. Tests require nil plans on unsafe output and preserve legitimate item-local rejects; these are contract tests, not real model/process integration.", - "evidence": [ - "TestAccountImportPlanKeepsCrossChunkConflictPriorityAndScope checks four bounded calls and legitimate create/update outputs alongside both duplicated rejects.", - "New mutation cases assert the exact stage reached, counters, original policy codes and non-execution. Six exact top-level tests observed RUN/PASS; see v027-astra-import-integrity-review.json." - ] - }, - { - "path": "backend/internal/service/plugin_account_tools.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "55a684f14af1c5ee1e98c535217686d8365979dad082c58c83e67b623e208d86", - "review_fingerprint": "55a684f14af1c5ee1e98c535217686d8365979dad082c58c83e67b623e208d86", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "Full-file review: preserve global planning helpers while adding an account-scoped invocation path for custom test options.", - "evidence": [ - "accountToolsOperation retains AccountID=0 for existing non-account/shared planning, taxonomy and batch operations.", - "accountToolsOperationForAccount passes the host account's platform/type/ID into the common encoder and Invocation.AccountID; nil account fails rather than panicking.", - "Two-second deadline, typed errors, output decoding and optional owner capture remain unchanged. No RPC capability changes: account-tools still invokes CapabilityAdmin." - ] - }, - { - "path": "backend/internal/service/plugin_account_view_jobs_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7a8f10266eebe6fde6f2315dafd162dde7f584de3146ded1bb49d9dbbb6dc2f4", - "review_fingerprint": "7a8f10266eebe6fde6f2315dafd162dde7f584de3146ded1bb49d9dbbb6dc2f4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "下游新增的 unit 测试(//go:build unit,235 行,上游无此文件),验证账号视图上下文与账号任务宿主的绑定规则:视图上下文里泛化的 extension-operation 任务在 Submit/ReplaySubmission/PrepareAccountJob/ExecuteAccountJob 四处都被 ErrAccountViewUnsupportedOperation 拒绝,只有后台 WithPluginExecution 上下文可提交且不盖视图印记;原生 core 任务不被插件接管、drain 时通过 repo.Cancel 结算;视图任务元数据同时记录执行插件(id 2)与视图来源(plugin 1/RuntimeGeneration)且不泄漏搜索词;重放先于目录读取、不同 PresetID 触发幂等冲突、RetryFailed 保留加密载荷并采用新 generation、旧 generation 元数据被 BindAccountJobView 拒绝;核心任务的 sha256 请求哈希与 24h TTL 不变;Cindy cleanup 任务的 BindAccountJobExecution 在 RolloutPercent 变化后失败、无元数据的旧 cindy_banned_cleanup 记录由 PrepareAccountJob 解析归属且不回写。被测对象全部是核心任务宿主机制(account_job_plugin.go、plugin_jobs.go、plugin_account_views.go),归 core-extension-and-job-host。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S57-plugin-manager-T1-review.json", - "New downstream (git ls-tree aea725f prints nothing); 7 tests L19-L235: TestAccountViewGenericRPCJobsAreUnsupported, TestAccountViewNativeJobCancellationKeepsHostProgress, TestAccountViewReplayIdentityAndFrozenRetry, TestAccountViewCoreJobHashAndTTLUnchanged, TestCindyCleanupBindAndExecuteAdmission, TestLegacyCindyCleanupExecutionOwner, TestAccountViewDuplicateJobTargetsDoNotLoseLosers.", - "Subjects located with rg: BindAccountJobExecution/BindAccountJobView/stampAccountJobView/accountViewJobTargets in account_job_plugin.go L72/L284/L254/L338; NewPluginJobExecutor in plugin_jobs.go L26; BindAccountViewRequest + ErrAccountViewUnsupportedOperation in plugin_account_views.go L420/L27; fixtures newViewFixture/applyViewFixture in plugin_account_views_test.go L133/L163; job-kind constants AccountJobKindCindy*/Duplicate* in account_job.go L28-L31.", - "L113 asserts job.Metadata does not contain the private search string (no view query leakage into persisted metadata); L143/L147 assert generation pinning on retry and rejection of a stale generation; L216 asserts legacy records are not rewritten.", - "Observation carried to plugin_jobs.go review: L203-L221 imply the executor resolves the owner of legacy cindy_banned_cleanup jobs by plugin key; whether that mapping is host-declared or plugin-declared is judged in the plugin_jobs.go entry.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/plugin_account_view_resources_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "59f739c14a4de97e7f438c060f682a784c009c0289e71f0602b73500b81027c3", - "review_fingerprint": "59f739c14a4de97e7f438c060f682a784c009c0289e71f0602b73500b81027c3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "下游新增的 unit 测试(96 行,上游无此文件),验证宿主资源准入机制:固定全域的 cleanup 资源策略只取决于 provider 与 admin 两个 binding 的 RolloutPercent 是否都为 100,与视图 preset/search/选中账号无关(5 组用例);ResourceDescriptors 的可用性缓存按固定域区分而不是按名字共享,禁用 Admin binding 后 Contributions() 为空;插件禁用后 BindRetainedAccountView 只给出非业务的保留目录,保留读描述符可用、创建描述符不可用且 BindAccountViewRequest 报错,序列化含 retained:true;带 RowPredicate 的 account.actions 资源动作要求 provider+admin 两种能力,且 ValidateResourcePolicy 会对账号 ID 重新校验行谓词而不只依赖 UI 隐藏。被测对象是 plugin_resources.go / plugin_account_views.go / plugin_contribution_admission.go 的核心准入机制,归 core-extension-and-job-host。测试以 Cindy 命名的策略与谓词作为夹具(CindyCleanupResourcePolicy、cindy.probe.get、CindyOnly/CindyBalanceStatus),这些名字是否应由插件声明在 plugin_resources.go 条目中判断。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S57-plugin-manager-T1-review.json", - "New downstream (git ls-tree aea725f prints nothing); 4 tests L14-L96: TestCindyCleanupFixedScopeResourceAdmission (rollout matrix L18), TestCindyCleanupResourceAvailabilityCache (L36-L54), TestAccountViewRetainedCatalogDoesNotAuthorizeNewIO (L56-L81), TestAccountViewResourceActionRequiresAdminAndRowPredicate (L83-L96).", - "Subjects located with rg: ValidateResourcePolicy plugin_resources.go L207, ResourceDescriptors L155, CindyCleanupResourcePolicy L301; BindRetainedAccountView / AccountViewFromContext plugin_account_views.go L314/L281; contributionRequiredCapabilities plugin_contribution_admission.go L35; Contributions plugin_extensions.go L319; predicate fields CindyOnly/CindyBalanceStatus in pkg/extensionapi/v1/account_view.go L25-L26.", - "L30 and L48 assert admission and cache identity depend on the fixed domain, not on the caller's view state; L74-L77 assert a retained catalog never authorizes new IO or a business view binding; L95 asserts the row predicate is re-checked server-side.", - "Observation: the fixtures rely on Cindy-specific vocabulary exported from core (CindyCleanupResourcePolicy) and from the SDK predicate type; ownership of that vocabulary is judged in the plugin_resources.go entry, not here.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/plugin_account_views.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "65db67e99060fcaa517b9402b082db8967acd62e59b9bbf99108ed539010f749", - "review_fingerprint": "65db67e99060fcaa517b9402b082db8967acd62e59b9bbf99108ed539010f749", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_account_views_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "980a15829d512e9f80fb5ba74ee227046e0bf9bc420d236f6030f7bbb8e06e99", - "review_fingerprint": "980a15829d512e9f80fb5ba74ee227046e0bf9bc420d236f6030f7bbb8e06e99", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "下游新增的 unit 测试与共享夹具(408 行,上游无此文件)。L24-L169 定义 viewFixtureRepo/viewFixtureLease/viewFixtureDirectory 与 newViewFixture/applyViewFixture:两个安装(Cindy 账号视图拥有者 id 1、codexrip.account-tools id 2)、四个带合成凭据的账号目录,凭据/身份 API 一旦被调用即报错。7 个测试验证宿主账号视图机制:validateAccountViewContributions 拒绝跨拥有者引用、未声明的 core 过滤面引用、未知 source、双表、preset 冲突、manifest ID 不一致、缺 admin 能力、把 credentials.api_key 绑到展示字段,且 AccountViewDefinitionV1 反序列化拒绝 base_query.sql;plugins/cindy-provider/manifest.source.json 的账号视图声明通过校验;BindAccountViewRequest 校验 PluginKey/PackageSHA256/安装唯一性且不夺取插件执行归属;ValidateAccountViewTargets/ValidateAccountViewPredicateQuery 与 ListAccountsConsole、GetAccountConsoleFacets 在聚合前按视图范围裁剪(sqlmock 校验 SQL 次数),preset 计数按 base+scope 计算;视图+资源双归属的 fence 顺序、UI 资产会话绑定 actor 与视图身份、token claims 不含搜索词与 api_key、runtime drain 取消上下文并释放两把 lease;BuildCindyDuplicateIdentityInventory 在调用扩展聚合前按视图过滤候选且载荷不含私钥。被测对象是 plugin_account_views.go、plugin_resources.go、plugin_manager.go(UI 会话)与 admin 侧的视图作用域适配,属核心机制,归 core-extension-and-job-host。静态阅读,未执行;sqlmock 仅是测试替身,未连接数据库。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S57-plugin-manager-T1-review.json", - "New downstream (git ls-tree aea725f prints nothing). Fixtures L24-L169; tests L171-L408: TestAccountViewManifestContract (8 negative sub-cases L175-L198 + 2 raw JSON rejections L199), TestAccountViewCindySourceDeclaration (reads plugins/cindy-provider/manifest.source.json, L205), TestAccountViewOwnerQualifiedResolution (L222), TestAccountViewScopeBeforeAggregation (L267), TestAccountViewFacetRelaxationAndPresetCounters (L297), TestAccountViewDualOwnerLifetimeAndUICapture (L320), TestAccountViewDuplicateInventoryFiltersBeforeAggregation (L367).", - "Subjects located with rg: validateAccountViewContributions plugin_account_views.go L72, AccountViewDefinitionDigest L235, ValidateAccountViewTargets L579, ValidateAccountViewPredicateQuery L635; cloneHostIOInstallation plugin_host_io_admission_test.go L86; extensionAccount plugin_extension_accounts.go L11; PluginExecutionFences / CreateUIAssetSession / ValidateUIRequestBinding / parseUIAssetToken exercised on PluginManager (plugin_manager.go, reviewed in this slice).", - "Secret hygiene assertions: L111/L117 credential API must not be called; L345-L346 UI token claims contain neither the private search nor synthetic-private-key; L401 extension payload excludes the private key.", - "Observation: the fixture and several assertions depend on Cindy-named vocabulary exported from core (CindyAccountViewPluginKey, CindyAccountViewID, PlatformCindy, ProviderProfileCindyLaxaV1, Account.CindyBannedAt, SDK AccountViewPredicate.CindyOnly/CindyBalanceStatus/CindyHealthStatus); plugin_account_views.go itself is outside this slice, the in-slice uses in plugin_jobs.go and plugin_resources.go are judged in their own entries.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/plugin_bootstrap_completion_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cccef479d27afed40919626930edc873e8855ff7fd5f91da04efb2769ebfae16", - "review_fingerprint": "cccef479d27afed40919626930edc873e8855ff7fd5f91da04efb2769ebfae16", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New in-memory repository fixture implements the full bundle port and runs actual bootstrapBundle using a valid non-runnable package. Four cases prove confirmed persisted takeover alone suppresses completion conflict; missing confirmation, ownership-read failure and unrelated storage error are preserved. All four cases actually ran, with no process/model execution.", - "evidence": [ - "artifacts/evidence/v027-astra-bootstrap-update-review.json: confirmed API interleavings, exact red/green RUN/PASS, bounded file conclusions and explicit pending scope" - ] - }, - { - "path": "backend/internal/service/plugin_broker_scope_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8a750e01527bb2cd1a34c7dd98a85324607063a44f354993113a03e4b1914924", - "review_fingerprint": "8a750e01527bb2cd1a34c7dd98a85324607063a44f354993113a03e4b1914924", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_bundle.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "6b4e026a374883d2080fe512bfbead6cdcafd7d66d82074a275ba5dc8428c20b", - "review_fingerprint": "6b4e026a374883d2080fe512bfbead6cdcafd7d66d82074a275ba5dc8428c20b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "拆出仅completed分支使用的handled helper,在fresh policy/state检查前不进入stage;移除/状态冲突要求持久确认。所有handled exits聚合本次候选清理,identity mismatch也清理未交接候选;未完成Prepare/import/complete代码保持原样。", - "evidence": [ - "bootstrap call site:139-144", - "handleCompletedBundledCandidate", - "fresh bundled/non-updating guard", - "confirmCompletedBundleTakeover", - "T-002", - "T-003", - "artifacts/evidence/v027-astra-bundle-pin-race-review.json: complete source scope; no process/PG publication executed" - ] - }, - { - "path": "backend/internal/service/plugin_bundle_pin_race_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2cd4f4375a1e831136e01a5399c231fc6579295f620f569b8d9ca39b1e180e1f", - "review_fingerprint": "2cd4f4375a1e831136e01a5399c231fc6579295f620f569b8d9ca39b1e180e1f", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "显式实现全部PluginRepository及Bundle/Update接口,并有编译期接口断言;不嵌入nil port来假装支持stage。真实Install+bootstrap,List/Stage/Prepare/import/complete有计数;unexpected写立即失败。旧artifact/binary和全部文件SHA、旧config/bindings/revision/generation断言保持。", - "evidence": [ - "completedBundleRaceRepository full methods", - "three interface assertions", - "completedBundleFixture actual installer", - "assertCompletedCandidateCleaned file hash/glob/runtime-directory assertions", - "T-001/T-002/T-003", - "artifacts/evidence/v027-astra-bundle-pin-race-review.json: complete source scope; no process/PG publication executed" - ] - }, - { - "path": "backend/internal/service/plugin_catalog_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a2112dd5a131d598ec3a8a16fc0240123403a6c52ac598140a2f401b38f6902b", - "review_fingerprint": "a2112dd5a131d598ec3a8a16fc0240123403a6c52ac598140a2f401b38f6902b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "Full-file test review with five new regression cases and the one existing cache test directly affected by the new guard.", - "evidence": [ - "Read all 244 final lines. Existing shared-query cache test still omits AccountID and preserves its old global reference behavior, clone isolation, disable/health checks and config-key invalidation.", - "New configuring/canceled cached-query subcases first failed against the old adapter, then passed without extra plugin calls.", - "Real Account lookup proves identical nonzero ID in CatalogQuery and Invocation, 0% exclusion, 50% bucket selection, 100% admission and account-partitioned cached results.", - "Persisted changes are supplied while the local registry remains old: disabled binding, 0% rollout, disabled state, replacement generation and changed encrypted config all prevent stale cache use. The repository records only six point reads of plugin ID 1.", - "A simulated config revision change during the RPC returns no entry and writes no cache; a later stable query succeeds/caches and inFlight returns to zero.", - "The namespace regression uses the actual host candidate builder/lookup with catalog.New(): 327 and 512 bytes match the existing GPT leaf, while both host and module reject 513 bytes. It failed before the 512-bound fix and passed after." - ] - }, - { - "path": "backend/internal/service/plugin_cindy.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "b89648ac3ac8735be29df51948a7ea38b5de8fcb5d933e20c14b7ec845af9e05", - "review_fingerprint": "b89648ac3ac8735be29df51948a7ea38b5de8fcb5d933e20c14b7ec845af9e05", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "全文45行:cindy.features是有界全局只读配置,错误/业务code/decode失败返回全零;cindy.health只传status、JSON有效性及六个结构化code/type字段,不传完整body/message/凭据。现把既有真实account.ID带入Invocation及manager缓存键/灰度准入,nil无决策;错误或部分反序列化必须清空整个健康/余额结果。共享pre-create ID0语义保留,持久化不在本文件。", - "evidence": [ - "artifacts/evidence/v027-cindy-policy-admission-decode-review.json", - "Full-file source reads 3108fc/090a5b/44501b/4e896c plus current patch and source-hash verification", - "No generic filename or test-name-only closure" - ] - }, - { - "path": "backend/internal/service/plugin_cindy_codex.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "efdcde72a4325689f5f650ea5f2ccf7ebd83b089b39697d9cdb62e8132aa8bfd", - "review_fingerprint": "efdcde72a4325689f5f650ea5f2ccf7ebd83b089b39697d9cdb62e8132aa8bfd", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "全文60行:插件描述计划必须与本次capability的PublicID、输入模态、上下文窗口和推理集合一致;校验shell/visibility/truncation、描述长度和32KiB总量,不允许插件替换native base instructions。只复制返回对象后填优先级/官方基础文本,选择、展示策略由provider拥有,未发IO或落库。", - "evidence": [ - "artifacts/evidence/v027-cindy-policy-admission-decode-review.json", - "Full-file source reads 3108fc/090a5b/44501b/4e896c plus current patch and source-hash verification", - "No generic filename or test-name-only closure" - ] - }, - { - "path": "backend/internal/service/plugin_cindy_codex_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2fecae56a94918c8f66ede00db3087898f960e2aa8e7d3a7e5487ddf40068323", - "review_fingerprint": "2fecae56a94918c8f66ede00db3087898f960e2aa8e7d3a7e5487ddf40068323", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_cindy_management.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "22ec5b144e2e1e2a6f06d93b24e21b2494d172822b523dfc898e8ebcfffc6630", - "review_fingerprint": "22ec5b144e2e1e2a6f06d93b24e21b2494d172822b523dfc898e8ebcfffc6630", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "Cindy/API Key 具名调用具有负载和期限限制;校验返回的名称、Key 集、指纹和源侧未扩大用户意图,插件不可用时拒绝。", - "evidence": [ - "backend/internal/service/plugin_cindy_management_test.go", - ".downstream/implementation-v0.2.7.md#可复用验证" - ] - }, - { - "path": "backend/internal/service/plugin_cindy_management_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e82edb9242b0c55b2a95d2dcf82f26fb3795e76ad1b74a83257768cfcb0474ea", - "review_fingerprint": "e82edb9242b0c55b2a95d2dcf82f26fb3795e76ad1b74a83257768cfcb0474ea", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "捕获真实独立模块负载,证明凭据及上游地址不出宿主,停用后清单和分组决策均拒绝。", - "evidence": [ - "plugins/cindy-provider/catalog/management_test.go", - ".downstream/implementation-v0.2.7.md#可复用验证" - ] - }, - { - "path": "backend/internal/service/plugin_cindy_probe.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "7471a0a119931f3cd3ccf916bf3c6aab32bad531e846bc3c6f5291f5dddad91c", - "review_fingerprint": "7471a0a119931f3cd3ccf916bf3c6aab32bad531e846bc3c6f5291f5dddad91c", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_cindy_probe_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "757cba5d36fa40a4787f28286f7fd5dcab84f1f0d0ee0fb0cc91c65147c3b0bf", - "review_fingerprint": "757cba5d36fa40a4787f28286f7fd5dcab84f1f0d0ee0fb0cc91c65147c3b0bf", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_codex_identity.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "5109f9249749ccf73625832abd145af118c6c4501a3649c4329347767a04c9c0", - "review_fingerprint": "5109f9249749ccf73625832abd145af118c6c4501a3649c4329347767a04c9c0", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_codex_identity_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c79b1c66deda5207b4ddf003430617aeb299d9317e26ecf7f2089101047c5617", - "review_fingerprint": "c79b1c66deda5207b4ddf003430617aeb299d9317e26ecf7f2089101047c5617", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "下游新增的测试(105 行,无 build tag,上游无此文件),验证宿主侧 Codex 身份桥接对 codex-runtime 扩展的 fail-closed 行为:当扩展的 codex.identity.available 返回可用但 derive/validate 不可用时,enforceCodexIdentityHeadersForAccountContext 不改写 Originator 头、prepareCodexTransport 与 RefreshAccountToken 都返回 ErrExtensionOperationUnavailable 且不设置 UA(不能回落到宿主内置的 canonical 身份);扩展提供方为 nil 时视为域已禁用:CodexClientIdentity 不可得、已存储的 codex_client_identity 数据在编辑时保留、指纹模式回落为 off 但上游显式的 session 模式仍生效、HTTP 透传不变;请求能力 binding 只覆盖 setup_token 账号类型时 OAuth 账号得不到身份;快照报告 account/override_ua 两种指纹来源。被测对象是 openai_codex_identity*.go、openai_codex_client_identity.go、openai_codex_fingerprint.go 与 plugin_codex_transport.go 里把身份推导委托给扩展操作的宿主桥接(通过 processExtensionOperations 调用 codex.identity.*),身份规则本身在插件内,故为 adapter / codex-runtime。静态阅读,未执行;不主张 plugin_codex_transport.go 等被测源文件本身已复审(不在本 slice)。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S57-plugin-manager-T1-review.json", - "New downstream (git ls-tree aea725f prints nothing). 4 tests: TestCodexIdentityPlanFailureCannotSendCanonicalFallback L24-L43 (partialCodexIdentityFailure L15-L22 returns valid only for codex.identity.available), TestCodexIdentityDisabledKeepsDataAndFailureBlocksHTTPAndRefresh L45-L76, TestCodexProfileMetadataDoesNotBroadenAccountBinding L78-L94, TestCodexIdentitySnapshotReportsTheSelectedFingerprintSource L96-L105.", - "Subjects located with rg: enforceCodexIdentityHeadersForAccountContext openai_codex_identity.go L288, SetCodexForceCLIEnabled L68; prepareCodexTransport plugin_codex_transport.go L36; CodexClientIdentity / ensureCodexClientIdentityExtra openai_codex_client_identity.go L124/L162 (CodexClientIdentityExtraKey L19); prepareCodexFingerprintExtraForUpdate / GetCodexFingerprintMode openai_codex_fingerprint.go L186/L238 (codexFingerprintSeedExtraKey L86); resolveCodexIdentitySnapshotContext openai_codex_identity_snapshot.go L47; fixtures ticketTestManager openai_codex_ticket_test.go L49, promptPolicyFixture plugin_prompt_fixture_test.go L21, failedPromptProcess prompt_domain_runtime_test.go L12, identityRefreshingOAuthClientStub openai_codex_client_identity_test.go L19.", - "Fail-closed anchors: L33-L34 headers untouched on plan failure; L38/L41-L42 transport and refresh blocked with empty UA; L71 explicit message 'policy failure cannot silently send canonical identity'; L60/L63 stored data and upstream explicit fingerprint policy survive a disabled domain.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/plugin_codex_recovery.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "b6a95ba025861f98ae20408ab51fdeaac536b21d470341052c470b027643799b", - "review_fingerprint": "b6a95ba025861f98ae20408ab51fdeaac536b21d470341052c470b027643799b", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "The host adapts protocol facts to declared operations, carries actual account ID/type for scope and rollout, restricts returned indices to existing cipher items, and validates replay rules against its supported protocol subset before cache use.", - "evidence": [ - "TestRecoverySelectionCannotEscapeActualAccountScopeOrRollout and private-material isolation passed" - ] - }, - { - "path": "backend/internal/service/plugin_codex_recovery_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a6759d70544587b137c7666b772039a9b5ae5bf6f0ec8bb115d799c99cdfb5fc", - "review_fingerprint": "a6759d70544587b137c7666b772039a9b5ae5bf6f0ec8bb115d799c99cdfb5fc", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Tests invoke the real independent recovery policy and real manager scope selection, verify private material is absent, and reject recovery after disable or outside the actual account/rollout while preserving core protocol classification.", - "evidence": [ - "targeted unit selection passed; existing disable regression result reused" - ] - }, - { - "path": "backend/internal/service/plugin_codex_scope_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "798fbee3bfafe8dda0aca9b6e4ebe39f7d2c5d6d4cee10ccf21f05adcc20bb03", - "review_fingerprint": "798fbee3bfafe8dda0aca9b6e4ebe39f7d2c5d6d4cee10ccf21f05adcc20bb03", - "review_status": "reviewed", - "decision": "reference", - "owner": "codex-runtime", - "reason": "使用真实 PluginManager/绑定/灰度选择,只 stub 插件进程边界;记录实际 Invocation.AccountID。覆盖 OAuth/setup-token、0/50/100%、in/out bucket、已有/派生 profile、真实 gateway sandbox 入口、transport、Extra 更新、快照、后台回填、刷新 client stub 及 runtime 缺失。共享创建前 helper 的 ID=0 正向契约也保留。", - "evidence": [ - "codexScopeFixtureManager records process-boundary invocations", - "TestCodexAccountPoliciesCarryActualScope eight paths", - "TestCodexAccountPolicyTypeDoesNotBecomeDomainScope", - "TestCodexSharedIdentityBeforeAccountCreationKeepsDomainSemantics", - "TestCodexIdentityBackfillUsesEachAccountScope", - "TestCodexIdentityBackfillUnavailablePolicyIsAccountScoped", - "TestCodexRefreshScopeAndUnavailableRuntime", - "Source review covers the complete named file; synthetic tests are not real token, model or database validation. Unchanged repository CAS code is not retested here." - ] - }, - { - "path": "backend/internal/service/plugin_codex_transport.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "1f8d0692704f7280abc9a69df55aac3f5fa88380cca0740c36a8116e3356b032", - "review_fingerprint": "1f8d0692704f7280abc9a69df55aac3f5fa88380cca0740c36a8116e3356b032", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "prepareCodexTransport 将现有 Account.ID 与 Type 传入 codexTransportPlan;Invocation scope 与请求元数据分离,仍不把请求正文或凭据交给策略。灰度外/明确停用返回不压缩计划,适用但不可用策略仍返回错误。", - "evidence": [ - "codexTransportPlan AccountID field", - "prepareCodexTransport ID/type forwarding", - "existing BodyPresent-only payload", - "v027-astra-codex-scope-review.json:T-001", - "v027-astra-codex-scope-review.json:T-004", - "Source review covers the complete named file; synthetic tests are not real token, model or database validation. Unchanged repository CAS code is not retested here." - ] - }, - { - "path": "backend/internal/service/plugin_compatibility.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "364a3b1395adb1437ad94d55316e938730a7b9b3728ef43b0f35bda5d41fdb0e", - "review_fingerprint": "364a3b1395adb1437ad94d55316e938730a7b9b3728ef43b0f35bda5d41fdb0e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "同时检查原 plugin/transport/UI 版本及可选 extension版本,再比较 semver范围和tested host。七包范围>=0.2.7-0容纳codexrip/candidate prerelease,不把单纯0.2.7测试值误当对所有host的动态执行证明。", - "evidence": [ - "EvaluatePluginCompatibility", - "matchesSemverRange", - "seven manifest requires fields", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": "backend/internal/service/plugin_config_receipt_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "de7511d25979880f434d06b7534a763a0031a117bf5b3a9767c34d812f610355", - "review_fingerprint": "de7511d25979880f434d06b7534a763a0031a117bf5b3a9767c34d812f610355", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New service tests use normalized-config and explicit repository/lease fixtures. They prove no rebase to another admin during write/apply, strong canonical receipt, unchanged-save CAS/no cancellation, and old-package admin action/job rejection before a runtime lease. Two existing direct config contracts passed unchanged.", - "evidence": [ - "artifacts/evidence/v027-astra-plugin-precondition-review.json: read/write receipt protocol, HTTP/Frame/API targeted outcomes and shared-file boundaries" - ] - }, - { - "path": "backend/internal/service/plugin_contribution_admission.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "3ef921d932043550fcc074395aa1fa4350feae9446e56b8667a0020ab2decffc", - "review_fingerprint": "3ef921d932043550fcc074395aa1fa4350feae9446e56b8667a0020ab2decffc", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文156行:复合声明只合并同一installation的主capability与Admin(action/resource_action/view/create/edit)及theme的UI;scope交集分别处理平台/账号类型、百分比取min,同一scope备选路径取max,保留union而不放大intersection,排序确定。非法百分比和disabled binding不能进入有效scope;theme/all_accounts需要全域双通配与100%,具体账号准入先拒绝非正ID,再用真实对象filter和每项能力的稳定bucket。可选capability的旧展示兼容分支仍无业务授权效力;Admin RPC及固定resource执行再次核其固有能力。appliedRevision在manager锁内比对包/代次/加密配置并拒绝configuring,无网络/数据库调用置于该短锁内。manifest schema漏all_accounts不影响此运行时门控,但schema本身另留pending。 本轮同SHA复核,未改源码或重复既有业务测试;原manifest/schema缺陷及修复在本报告单列,不能用本文件结论覆盖其他文件。", - "evidence": [ - "artifacts/evidence/v027-host-contract-final-integration-review.json#read_extent", - "artifacts/evidence/v027-host-contract-final-integration-review.json#evidence", - "artifacts/evidence/v027-astra-host-contract-full-review.json#read_extent" - ] - }, - { - "path": "backend/internal/service/plugin_contribution_admission_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "279eca13b1a748ee702c1d4e2942f3cfb427dcee0a7f3e7a057b2159bed15cc5", - "review_fingerprint": "279eca13b1a748ee702c1d4e2942f3cfb427dcee0a7f3e7a057b2159bed15cc5", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "New bounded Go tests exercise intersected scopes, host/TS bucket vectors, registry projection, early admin-action rejection and single-account test option scope. A new post-review regression also verifies fresh persisted config versus old applied runtime before any invocation.", - "evidence": [ - "Shared golden vectors assert uint64 buckets for IDs 1,2,3,42,1000 and 9007199254740991; the TypeScript test reads the same JSON.", - "Admin wildcard/OAuth 70 and OpenAI/SetupToken 100 intersect credential OpenAI/* 50 plus SetupToken 80 into exactly OpenAI/OAuth 50 and OpenAI/SetupToken 80; account 2/OAuth passes, 3/OAuth fails and 3/SetupToken passes.", - "Partial contributions stay present/available in the host registry with exact projected scope. Both Observability+Admin and Credentials+Admin reject account 3 or a persisted business-capability disable before dispatch.", - "Single-account custom prompt/reasoning invocations carry ID 2; ID 3 outside 50% gets an error. Blank prompt/effort skip plugin invocation and preserve native default semantics.", - "Legacy page presence without primary capability and scoped non-account shared management are explicitly retained.", - "TestContributionAdminAdmissionRejectsUnappliedConfiguration uses the complete-interface hostIOAdmissionRepository plus a positive serialized-RPC control. Persisted telemetry=false with runtime true now returns ErrExtensionOperationUnavailable and zero plugin calls; applied false, configuring, and restored matching true controls are checked in the same test." - ] - }, - { - "path": "backend/internal/service/plugin_credential_scope_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "112942ef9320d3f8423f72328ebb7cad3b4bf0b8f284df4597cb1838dbe1d91c", - "review_fingerprint": "112942ef9320d3f8423f72328ebb7cad3b4bf0b8f284df4597cb1838dbe1d91c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Direct host fixture distinguishes metadata request capability from credential access, permits a separately declared credential capability, and revokes it through the live allows callback. Resolver call counts show failures do not request credentials. Callback signature now carries account ID; the unchanged credential permission assertions were rerun once for that direct interface impact.", - "evidence": [ - "TestRequestPolicyCapabilityDoesNotImplyCredentialAccess observed RUN/PASS, synthetic token only.", - "artifacts/evidence/v027-broker-and-request-scope-review.json" - ] - }, - { - "path": "backend/internal/service/plugin_domain_operation.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "00dc82a8f8c066000529eb5c7ed7afdb7c79a0f509da039d426863782183ea4b", - "review_fingerprint": "00dc82a8f8c066000529eb5c7ed7afdb7c79a0f509da039d426863782183ea4b", - "review_status": "reviewed", - "decision": "adapter", - "owner": "codex-runtime", - "reason": "共享域材料可在无账号时解析 owner/scope;不同 owner 冲突仍 fail-closed。此次不通过一律要求正 AccountID 来封死 domain,而只把已有账号输入转到 typed/ID 路由;generic helper 正向测试明确证明仍可用。", - "evidence": [ - "domainOperationScope", - "invokeProcessDomainExtension", - "v027-astra-codex-scope-review.json:T-001 shared/pre-create method", - "Source review covers the complete named file; synthetic tests are not real token, model or database validation. Unchanged repository CAS code is not retested here." - ] - }, - { - "path": "backend/internal/service/plugin_domain_operation_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "79504c0100e98aae77d79230a48616505f9d79f11d4d80463bb8b20aea114be3", - "review_fingerprint": "79504c0100e98aae77d79230a48616505f9d79f11d4d80463bb8b20aea114be3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文静态读4个场景及scoped manager:管理/availability元数据沿已有活跃domain scope而不扩大账号request binding;disabled/unhealthy/多个owner分别拒绝;已绑定来源操作在drain取消;显式WithPluginExecution选择资源原owner而非另一scope同名操作。fake只提供serializedRPC和内存registry,无真实插件/数据库/同步下载,本轮未重跑。", - "evidence": [ - "Full source and boundaries: artifacts/evidence/v027-host-update-theme-completion-review.json", - "Current source/fixture read only; no additional execution implied." - ] - }, - { - "path": "backend/internal/service/plugin_error_diagnostics.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "9480bbde875a688ed9bc7c0d92cffa4d64eca7d73557a225bc763a00125e9a89", - "review_fingerprint": "9480bbde875a688ed9bc7c0d92cffa4d64eca7d73557a225bc763a00125e9a89", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "The bounded projection parses stored events, re-sanitizes typed diagnostic metadata and authorizes each persisted account against current generation and rollout. It never returns raw event documents, account names, URLs or request/error bodies.", - "evidence": [ - "TestPluginErrorDiagnosticsUseStoredAccountsAndRemovePrivateFields passed" - ] - }, - { - "path": "backend/internal/service/plugin_error_diagnostics_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e485b241602f0700d8c7d64ea091367114fd9e9e1f9793d4d084da81ae74f3d7", - "review_fingerprint": "e485b241602f0700d8c7d64ea091367114fd9e9e1f9793d4d084da81ae74f3d7", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "A mixed-scope event list proves spoofed platform metadata cannot override actual account identity, private strings are removed, and absent execution, excluded rollout and replaced generation return no facts.", - "evidence": [ - "targeted test passed" - ] - }, - { - "path": "backend/internal/service/plugin_extension_accounts.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "3f8b356fbb70e3cecc4129ccc35552dfcb539a06631ab2bb9cc5e1fd9e4e0ecc", - "review_fingerprint": "3f8b356fbb70e3cecc4129ccc35552dfcb539a06631ab2bb9cc5e1fd9e4e0ecc", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "核心账号目录facade只投影ID/平台/类型/状态/shadow、不可逆主体标识和更新时间revision,不复制Credentials或Extra。List的includeInactive传到原repo且本地再过滤;真正每插件/账号scope由broker准入。凭据解析只接受非shadow OAuth-like,PrepareCredentials复用既有打票上下文,token/账号headers/proxy只在受授权credentials操作中返回;没有新凭据存储。", - "evidence": [ - "Full source/fixture review: artifacts/evidence/v027-host-prompt-account-contract-review.json", - "Referenced broker/policy/runtime behaviors remain separately tested in existing scoped evidence; no new test success implied." - ] - }, - { - "path": "backend/internal/service/plugin_extension_accounts_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "802ca2d9b3345cf065ee566f55f7f6f27855544fd9498950318a5b9ffa293bd7", - "review_fingerprint": "802ca2d9b3345cf065ee566f55f7f6f27855544fd9498950318a5b9ffa293bd7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整静态读取一个inventory fixture:repo返回active/disabled/error,includeInactive=true断言查询status空且三项,false断言status=active且只一项。只证明目录筛选合同,不代替broker权限/凭据脱敏;本轮未执行。", - "evidence": [ - "Full source/fixture review: artifacts/evidence/v027-host-prompt-account-contract-review.json", - "Referenced broker/policy/runtime behaviors remain separately tested in existing scoped evidence; no new test success implied." - ] - }, - { - "path": "backend/internal/service/plugin_extension_package_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c02331c8f38ec6ee7335f8965a4960ac61d33439f4ba72b0b73ecfe27b4def41", - "review_fingerprint": "c02331c8f38ec6ee7335f8965a4960ac61d33439f4ba72b0b73ecfe27b4def41", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_extension_runtime_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d91492f3dafcfef3632e45a1a690f65a89ec56ed4cf08b97733f9c7a5370e1cd", - "review_fingerprint": "d91492f3dafcfef3632e45a1a690f65a89ec56ed4cf08b97733f9c7a5370e1cd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "下游新增的进程级可选集成测试(271 行,上游无此文件):7 个测试各自从 SUB2API_*_TEST_BINARY 环境变量取本地编译好的第一方插件二进制,未设置时 t.Skip;每个测试对二进制计算 sha256 写入 BinarySHA256、从 plugins//manifest.source.json 读版本、用 newPluginHostServiceServer + 只读的 extensionReadOnlyFixture 状态存储构造宿主 broker,再用 startPluginRuntime(15s 启动超时、临时 socket 目录)拉起 go-plugin 子进程,validateAndApplyConfig 后通过 runtime.extension.Invoke 走真实 RPC:codex-runtime 的 scheduling admit 返回 ticket_missing、model-policy 的 catalog resolve 返回 gpt-6-astra 上下文 1050000、prompt-skills 的 prompt.plan 与 skills.seed.index/chunk 分块拉取并校验每个文件 sha256 且总量超过 MaxPayloadBytes、admin-observability 的 telemetry.read 走作用域 metrics broker 且不解析凭据、image-tools 的 image.studio.plan 受 studio_enabled 门控并经真实传输执行 image.responses.plan、cindy-provider 的 cindy.pricing 快照、account-tools 的 taxonomy.name 归一化。测试主体是插件运行时进程宿主与 broker 机制(plugin_runtime.go / plugin_host_services.go),业务断言只用来证明每个域跑在独立进程里,归 core-extension-and-job-host。静态阅读,未执行、未编译任何插件二进制。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S57-plugin-manager-T1-review.json", - "New downstream (git ls-tree aea725f prints nothing). Helpers extensionReadOnlyFixture L17-L24, firstPartyTestVersion L26-L34; tests TestExtensionRuntimeUsesOfficialProcessAndHostBroker L36, TestCatalogExtensionRuntimeUsesIndependentProcess L71, TestPromptExtensionRuntimeUsesIndependentProcess L98, TestObservabilityExtensionRuntimeUsesScopedMetricsBroker L149, TestImageToolsExtensionRuntimeUsesIndependentProcess L179, TestCindyProviderExtensionRuntimeUsesIndependentProcess L217, TestAccountToolsExtensionRuntimeUsesIndependentProcess L247; every test skips without its SUB2API_*_TEST_BINARY env var (L37-L40 etc.).", - "Runtime entry points exercised, located with rg: startPluginRuntime plugin_runtime.go L53, pluginRuntime type L30, validateAndApplyConfig L178, status L289, kill L338 (all reviewed in this slice), beginDrain plugin_operation_context.go L144; host broker newPluginHostServiceServer plugin_host_services.go L77 and pluginExtensionHost plugin_extension_state.go L28 (outside this slice); test doubles credentialScopeDirectory plugin_credential_scope_test.go L14, trafficPolicyCache plugin_observability_test.go L153.", - "Isolation anchors: L67-L68 comment and read-only state fixture mean no token resolver or upstream HTTP exists; L176 asserts metrics access resolves no credentials; L135/L146 assert chunked seed transfer respects MaxPayloadBytes per RPC while the whole seed exceeds it.", - "Observation: L240-L244 use core helper queryCindyPricingSnapshot (cindy_pricing_snapshot.go L179) and type CindyTextPricing to read the plugin's pricing snapshot; that helper is outside this slice and is not judged here.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/plugin_extension_state.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "820654f0505901adeefd0d9a9d3c0aeeae9b3a8a877a6eca06cdfd62e6cc2759", - "review_fingerprint": "820654f0505901adeefd0d9a9d3c0aeeae9b3a8a877a6eca06cdfd62e6cc2759", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_extensions.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "a92d1bb7aa0dd05ee3b6ea398b894b132bbbcf0e4a1f0967147aefb4a557938f", - "review_fingerprint": "a92d1bb7aa0dd05ee3b6ea398b894b132bbbcf0e4a1f0967147aefb4a557938f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文478行:Admin操作仅选同installation声明且permission=admin的action,宿主覆盖/删除payload account_id,账户类slot要求正ID,并用真实目录对象检查filter、能力与bucket。当前package/generation/state、已应用配置、进程drain/退出、最终configRevision与独立业务lease分层复核;静态registry可用性只是展示,不替代业务准入。注册冲突检查涵盖重叠operation owner、独占transport/provider、依赖存在和环路;发布用独立registry对象。公开投影仅主题和user surface,去掉action/entrypoint/条件/fields/filter/assets/display/account_scope;受限声明不能借该通道变成public授权。View/Create/Edit digest与generation附加字段同当前定义生成。七包均通过公开capability/operation/resource接口接入,文件本身没有嵌入其业务执行表或SQL/URL/命令求值器。 本轮同SHA复核,未改源码或重复既有业务测试;原manifest/schema缺陷及修复在本报告单列,不能用本文件结论覆盖其他文件。", - "evidence": [ - "artifacts/evidence/v027-host-contract-final-integration-review.json#read_extent", - "artifacts/evidence/v027-host-contract-final-integration-review.json#evidence", - "artifacts/evidence/v027-astra-host-contract-full-review.json#read_extent" - ] - }, - { - "path": "backend/internal/service/plugin_extensions_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f11aa59a9480748355de8fbb693706fcc60a0ac7e245ef0fef0e17f967dfec32", - "review_fingerprint": "f11aa59a9480748355de8fbb693706fcc60a0ac7e245ef0fef0e17f967dfec32", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整静态阅读四项断言:公开user surface在故障时保留不可用、关闭flag/停用binding时移除,JSON不含管理入口/flag;desired enabled与实际故障分别处理;每贡献自己的capability可独立撤下;provider dependency严格依绑定启停。本轮未重跑,不把内存贡献fixture当HTTP授权或真实进程验收。", - "evidence": [ - "source assertions in TestPublicPluginSurfaceRetainsFailureAndHidesDisabledConfiguration, TestPluginExtensionDesiredStateAndContributions, TestContributionFollowsItsOwnCapabilityWhileOtherCapabilitiesRemainEnabled, TestPluginExtensionDependenciesRespectEnabledBindings", - "Full current file read in parent review; not merely symbol or filename classification." - ] - }, - { - "path": "backend/internal/service/plugin_feature_decode_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "31ff36d6a7026a8d8beafce3c39811a8fe7f52c4693d7ed9c56a99a2f23f7884", - "review_fingerprint": "31ff36d6a7026a8d8beafce3c39811a8fe7f52c4693d7ed9c56a99a2f23f7884", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "全文75行纯fake响应:Cindy与Image features的部分类型错误不能留下true开关,健康/余额双字段部分decode不保留信号;合法显式布尔正控不变。每子例恢复全局invoker;不打开UI/模型/网络或更改运行配置。", - "evidence": [ - "artifacts/evidence/v027-cindy-policy-admission-decode-review.json", - "Full-file source reads 3108fc/090a5b/44501b/4e896c plus current patch and source-hash verification", - "No generic filename or test-name-only closure" - ] - }, - { - "path": "backend/internal/service/plugin_host_io_admission_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2dc34299b235ad1c3400afe9e7698e69fa5cca23a974f932a26217ad89b9fd0a", - "review_fingerprint": "2dc34299b235ad1c3400afe9e7698e69fa5cca23a974f932a26217ad89b9fd0a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整读两个目标方法和完整repository/locker fixture,无嵌入未实现端口制造假失败。正控拿到business lease再模拟持久disable/config/rollout revision变化并拒绝;fresh DB对象配旧应用config/generation/package在申请lease前即拒绝。断言active/inFlight归零及business-purpose标记不泄漏。复用该完全相同生产机制已有运行证据,本轮仅静态阅读不重跑。", - "evidence": [ - "artifacts/evidence/v027-astra-host-io-admission-review.json", - "Full current file read in parent review; not merely symbol or filename classification." - ] - }, - { - "path": "backend/internal/service/plugin_host_services.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "c9a5e1f06b770054194998ce333452200d234b5770db865359dc95f668f29c3d", - "review_fingerprint": "c9a5e1f06b770054194998ce333452200d234b5770db865359dc95f668f29c3d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文读取官方兼容HostService适配:pluginKey由宿主实例注入,namespace/key仅ASCII有限字符与长度,拒绝Redis glob/冒号;值256KiB、list≤1000、TTL先按整数比较90天避免溢出。账户目录仅注入端口能访问,要求正ID。新扩展API不再获得本Legacy store/directory;原transport-only行为和proto未变。", - "evidence": [ - "Source, red/green and compatibility limits: artifacts/evidence/v027-legacy-extension-port-review.json", - "Full static file read except explicitly partial manager; unchanged tests are not new pass evidence." - ] - }, - { - "path": "backend/internal/service/plugin_host_services_broker_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "7b7f005b854bd45f631f7441cd9b96b222b2df0f64800f6fef01efa203193b74", - "review_fingerprint": "7b7f005b854bd45f631f7441cd9b96b222b2df0f64800f6fef01efa203193b74", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_image_bridge.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "2e3f9941e7ffea90fe84721913140fd863ea45ee4016ab8a30fe08cdfa639468", - "review_fingerprint": "2e3f9941e7ffea90fe84721913140fd863ea45ee4016ab8a30fe08cdfa639468", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_image_bridge_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9984fa9cb22f205931c7b9666a149050fde6bb6d535fb46231d4a188917fc09e", - "review_fingerprint": "9984fa9cb22f205931c7b9666a149050fde6bb6d535fb46231d4a188917fc09e", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_image_tools.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "97851e1a40adca1b2fa21849f942bd1e5ccf299b55e68888cf050edee09a5e6c", - "review_fingerprint": "97851e1a40adca1b2fa21849f942bd1e5ccf299b55e68888cf050edee09a5e6c", - "review_status": "reviewed", - "decision": "adapter", - "owner": "image-tools", - "reason": "全文复核115行:native验证只传有界model/controls、boolean参考图事实和同一账号目录中的capability/verified,不含prompt、URL、图片内容;AccountID及ctx沿真实账号调用,策略仍在image-tools进程。features解析失败全零/不可用,Studio plan只接受固定原生端点、单张及b64_json;宿主保留协议校验,不复制插件控制规则或发任意请求。", - "evidence": [ - "artifacts/evidence/v027-astra-cindy-native-image-snapshot-review.json", - "artifacts/evidence/v027-cindy-policy-admission-decode-review.json", - "Full current source read including currentImageToolsConfig, ValidateCindyImageRequestForAccount, EnsureImageStudioAvailable and planImageStudio; previous zero-on-decode function unchanged, targeted results reused." - ] - }, - { - "path": "backend/internal/service/plugin_install_guard_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "00fc459b7b64037319cd3de0de1272c8f1eeba1c046fe36697063405bb14aa54", - "review_fingerprint": "00fc459b7b64037319cd3de0de1272c8f1eeba1c046fe36697063405bb14aa54", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New service regressions reject all six installed lifecycle states, including updating and same-version changed content; assert typed 409, no repository install mutation, retained previous local installation and files, and removal only of the rejected candidate. They also cover a database conflict after an empty lookup and successful disabled first install. All three top-level functions ran.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Actual targeted execution is recorded in verification below." - ] - }, - { - "path": "backend/internal/service/plugin_jobs.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "8d144450e2686fbac9563dc7df5a5b4d8939cd4e180d76cb887986c9c619b004", - "review_fingerprint": "8d144450e2686fbac9563dc7df5a5b4d8939cd4e180d76cb887986c9c619b004", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_legacy_host_port_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d8075e850a5baab7e298382c0715dd7b7438250c5f29dc69529b26765b6552b0", - "review_fingerprint": "d8075e850a5baab7e298382c0715dd7b7438250c5f29dc69529b26765b6552b0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "新合成测试先复现requires.extension_api进程仍可KVSet到同pluginKey空间;修复后其KVSet/Delete返回Unavailable且Store未写,具名extension broker仍非nil。对照legacy transport-only同一KV合同仍成功,未移除官方协议或改proto。", - "evidence": [ - "Source, red/green and compatibility limits: artifacts/evidence/v027-legacy-extension-port-review.json", - "Targeted test invoked only synthetic store; untouched official legacy succeeds." - ] - }, - { - "path": "backend/internal/service/plugin_manager.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "c3255f61d29081c1228b91b7c4a71ee963e520e5ceec805d790d75c9f803bef4", - "review_fingerprint": "c3255f61d29081c1228b91b7c4a71ee963e520e5ceec805d790d75c9f803bef4", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_manifest.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "503ffb6bacbde2228fd3c65ab2463fb2ef80b1ef423b8621707a5f28e6750b43", - "review_fingerprint": "503ffb6bacbde2228fd3c65ab2463fb2ef80b1ef423b8621707a5f28e6750b43", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整文件由先前388行全文读取加d771c8b79完整双hunk差异复核构成(当前389行)。不能无条件复用旧green:先前全文结论漏过resources名字正则与实际Prompt Audit资源不兼容,补充审查已撤回pending。本次仅新增预编译pluginResourceNamePattern并用于原Name检查,允许每dot段内非空dash词;max100、最多256资源、去重、admin/user权限和声明能力检查保持。实际UI capability资源fixture的负证据与父级本次绿方法证明修复目标;不扩大route/dispatch/任意URL、SQL、路径或命令能力。原清单版本、有限view/create/edit、包内资源/摘要与安装strict decoder机制结论继续有效。", - "evidence": [ - "artifacts/evidence/v027-host-contract-final-integration-review.json#read_extent", - "artifacts/evidence/v027-host-contract-final-integration-review.json#evidence", - "artifacts/evidence/v027-astra-host-contract-full-review.json#read_extent", - "artifacts/evidence/v027-astra-host-contract-resource-followup.json#findings", - "artifacts/evidence/v027-host-contract-final-integration-review.json#review_history_correction" - ] - }, - { - "path": "backend/internal/service/plugin_manifest_schema_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c81a6b2ae74f8dd5ee5684bd7c0153408d2bf73397b3a702c023d5b8e1234e3d", - "review_fingerprint": "c81a6b2ae74f8dd5ee5684bd7c0153408d2bf73397b3a702c023d5b8e1234e3d", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "当前130行从首行到EOF完整读取:三方法分别反射Go Contribution JSON字段核closed schema父properties和all_accounts boolean;复制实际admin-observability Resources及同源Capabilities到testPluginManifest(nil)有效runtime/files基线并调用真实Validate;读取schema两资源pattern与生产Go pattern精确比对,并经真实Validate拒绝重复/尾随dash、下划线、连续dot、路径、单段、大写、超长、重复grant和未声明能力。原测试的Admin-only/实际UI资源错配已改为source.Capabilities;没有改生产资源权限以迎合fixture。fixture只读文件及内存验证,不安装包、启动进程或访问网络。运行结果复用父级dc6572三方法实绿,本子任务未重跑。", - "evidence": [ - "artifacts/evidence/v027-host-contract-final-integration-review.json#read_extent", - "artifacts/evidence/v027-host-contract-final-integration-review.json#evidence" - ] - }, - { - "path": "backend/internal/service/plugin_observability.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "d6f9c203bb9d912d474d79139382cda5ba1a5c9b12ee58f96360a5dfbbfca0cc", - "review_fingerprint": "d6f9c203bb9d912d474d79139382cda5ba1a5c9b12ee58f96360a5dfbbfca0cc", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "Full-file review and account-aware policy lookup: observation admission now preserves positive account ID and concrete platform/type without changing the policy protocol or payload.", - "evidence": [ - "Read all 47 final lines. LegacyAdminObservabilityConfig remains bootstrap-only configuration import.", - "currentAccountTrafficObservationPolicy rejects nil/nonpositive/missing/wildcard account identity before invoking any plugin, then delegates with the actual platform/type and Invocation.AccountID.", - "resolveTrafficObservationPolicy retains its 100ms deadline, explicit Observability operation, empty JSON payload, result/code validation, DecisionTable validation and closed allowed outcome labels.", - "The unscoped helper remains only for management availability and pure classification compatibility; production Begin/Snapshot do not call it. No credentials, account body, new database query or new public SDK field was introduced." - ] - }, - { - "path": "backend/internal/service/plugin_observability_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d63b82b42c01bc3c6b261e0afc2a51f05678c2c635568e76a1cda6851c5432d9", - "review_fingerprint": "d63b82b42c01bc3c6b261e0afc2a51f05678c2c635568e76a1cda6851c5432d9", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "Full-file review with scope/missing-identity regressions; only the directly impacted existing captured-Finish case was rerun.", - "evidence": [ - "Read all 207 final lines. The scope fake wraps a concrete PluginManager with the actual cached operation selector and a serialized fake RPC into the independent observability module; there is no incomplete embedded interface or real network call.", - "The 7 scope cases run both HTTP/WS Begin and Snapshot: wildcard 0%, 50% included ID2/excluded ID3, wildcard 100%, matching OpenAI/OAuth binding, wrong platform, and wrong type.", - "Assertions verify cache target IDs/protocol, positive/zero RPC calls, exact routed platform/type/Invocation.AccountID, empty policy payload and no cache Begin/Snapshot for denied accounts.", - "The first run with unchanged production code failed: 0%/50%-excluded accounts were accepted, scoped-positive was denied, and observed identity was '*'. The same scope matrix passes after the fix.", - "Missing nil/zero/empty/wildcard identity produces no policy invocation or cache access. Existing Finish-after-disable test changes only its account fixture: the captured outcome still records once, duplicate Finish is ignored and later Begin is denied.", - "The separate metrics-broker test was read but not rerun or modified; the broker itself remains unchanged." - ] - }, - { - "path": "backend/internal/service/plugin_operation.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "18411dac0c0d70bb2f832658a32fea9404fd0fffc76a3f2375809ee4ec2dc01c", - "review_fingerprint": "18411dac0c0d70bb2f832658a32fea9404fd0fffc76a3f2375809ee4ec2dc01c", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_operation_admission.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "d7f4951dd15a54478e0c2739803aa86a6fb1200d99ed13df19cb7e1c6c56a76b", - "review_fingerprint": "d7f4951dd15a54478e0c2739803aa86a6fb1200d99ed13df19cb7e1c6c56a76b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整新内部准入实现:先拒绝取消/负账号,点读持久ID并核同包/执行代次、enabled及当前scope/已声明operation;既有业务租约核精确revision/config。按当前进程configRevision验证调用结果,取消、排空或apply跨代结果不能返回。无repo的纯进程契约fixture保留显式内存端口,生产调用始终持久端口。", - "evidence": [ - "Detailed source/commands: artifacts/evidence/v027-named-policy-admission-review.json", - "Eight exact new leaves plus four directly affected existing methods; no real model/DB requests." - ] - }, - { - "path": "backend/internal/service/plugin_operation_admission_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "344e392710e82a0b97254c762b03a1620d6aa4e7dfcd5800c1a4a1d72991fd60", - "review_fingerprint": "344e392710e82a0b97254c762b03a1620d6aa4e7dfcd5800c1a4a1d72991fd60", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_operation_context.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "fc1944255bb1b18fc2863bd92b2fabe87940e4d51fee39451e9097b7b80ae6e6", - "review_fingerprint": "fc1944255bb1b18fc2863bd92b2fabe87940e4d51fee39451e9097b7b80ae6e6", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文复核策略生命周期:client断开可脱离但独立policy cancellation保留;每次绑定对应用runtime identity/config,inFlight与专用business lease保留到真实cleanup,失联观察只撤销信号不提前释放。release/cancel均once,policy map在锁内维护和清理。内存契约invoker没有binder时只保留调用方取消;实际持久repository精确revision由既有lease协议核验。", - "evidence": [ - "artifacts/evidence/v027-astra-host-io-admission-review.json", - "artifacts/evidence/v027-astra-runtime-lease-loss-review.json", - "artifacts/evidence/v027-named-policy-admission-review.json", - "Full current file read in parent review; not merely symbol or filename classification." - ] - }, - { - "path": "backend/internal/service/plugin_operation_context_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "29f9fced65392e055ca6d9aa960f6b597703f747ddafb2b8f4f0b7160514b340", - "review_fingerprint": "29f9fced65392e055ca6d9aa960f6b597703f747ddafb2b8f4f0b7160514b340", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文读取独立policy信号的真实context断言:client取消后stream/nonstream upstream继续而plugin drain取消其IO,billing仍可收尾;迟到detach已取消,configuring/disable阻止新上下文;规范化同配置不再apply或取消工作,真正配置改变会取消。测试无真实网络/数据库,本轮未重跑。", - "evidence": [ - "Full source/fixture review: artifacts/evidence/v027-host-prompt-account-contract-review.json", - "Referenced broker/policy/runtime behaviors remain separately tested in existing scoped evidence; no new test success implied." - ] - }, - { - "path": "backend/internal/service/plugin_operation_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ef8a4c79f5c71e4439cdfefdee304aa01c34b792f26b3409dc8280a3122e79f5", - "review_fingerprint": "ef8a4c79f5c71e4439cdfefdee304aa01c34b792f26b3409dc8280a3122e79f5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文读取三个现有测试:保护Authorization/framing/tenant头、非法大小写重复/CRLF及全量原子应用;两个独立域具名调用不交叉并由宿主覆盖PluginID;重叠通配scope的同操作所有者拒绝,停用/改名解除冲突。仅其中具名分派方法因本次直接影响复验,其他不冒称再次执行。", - "evidence": [ - "Detailed source/commands: artifacts/evidence/v027-named-policy-admission-review.json", - "Eight exact new leaves plus four directly affected existing methods; no real model/DB requests." - ] - }, - { - "path": "backend/internal/service/plugin_package.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "9efc604a1131d0201d4b5f9783bbbc52400e6c2aa0efab8d78c683c2ee4801f0", - "review_fingerprint": "9efc604a1131d0201d4b5f9783bbbc52400e6c2aa0efab8d78c683c2ee4801f0", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_package_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3a49074ffae83819f52d574fce61c1c762dddc22e49d422090dffe6b2bd6fa91", - "review_fingerprint": "3a49074ffae83819f52d574fce61c1c762dddc22e49d422090dffe6b2bd6fa91", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Full fixture and assertion review: explicit unsigned-development opt-in is separate from default rejection; synthetic Ed25519 keys validate trusted signatures; repeated package extraction gets unique paths without replacing prior files; traversal/hash mismatch and actual extraction cap reject. Foreign-runtime verification checks matching runtime and every asset without executing the word-binary fixture. Config cannot replace the built-in transport key by reusing its key ID.", - "evidence": [ - "Ten top-level installer/verifier cases and helper construction read. No new runs: this file and production package code were unchanged. This verifies test intent, not fresh release artifact contents or OS-level sandboxing.", - "artifacts/evidence/v027-plugin-package-static-review.json" - ] - }, - { - "path": "backend/internal/service/plugin_precondition.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "92c33c9e4d571020e8d069283044ba0c4be00d199ecd4d8331f76391bb92b5d5", - "review_fingerprint": "92c33c9e4d571020e8d069283044ba0c4be00d199ecd4d8331f76391bb92b5d5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New internal expected-package context and optional strong config receipt port. Snapshot is raw config plus revision/package. The old method shape remains for internal fixtures; production HTTP SaveConfigSnapshot rejects missing strong receipt support instead of inventing a revision.", - "evidence": [ - "artifacts/evidence/v027-astra-plugin-precondition-review.json: read/write receipt protocol, HTTP/Frame/API targeted outcomes and shared-file boundaries" - ] - }, - { - "path": "backend/internal/service/plugin_prompt_fixture_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "89aa5fc58d3967c258aae1f239603ed6c67d90f5b48d2b933e73448c3066804a", - "review_fingerprint": "89aa5fc58d3967c258aae1f239603ed6c67d90f5b48d2b933e73448c3066804a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整读取仅_test构建的进程边界fixture;按recovery/codex identity/transport/observability/image/Cindy/account-tools命名分派到独立模块,Cindy/image用合成legacy config适配测试,余下归prompt。init只安装测试进程provider,不进入生产构建;不同域规则未复制回宿主执行器。", - "evidence": [ - "Full source/fixture review: artifacts/evidence/v027-host-prompt-account-contract-review.json", - "Referenced broker/policy/runtime behaviors remain separately tested in existing scoped evidence; no new test success implied." - ] - }, - { - "path": "backend/internal/service/plugin_prompt_management.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "767d021437e1097f616ec9e55144ff914c07602a639e3f4ec42fbfd6f5015ddb", - "review_fingerprint": "767d021437e1097f616ec9e55144ff914c07602a639e3f4ec42fbfd6f5015ddb", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_prompt_profile_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5671f44b3d8b07a508283dbaa6dcf12f5fe94cb99631c7ba4a8721fb3e19c0db", - "review_fingerprint": "5671f44b3d8b07a508283dbaa6dcf12f5fe94cb99631c7ba4a8721fb3e19c0db", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文读三个规则fixture:固定source/upstream/public origin不能被插件改成loopback/foreign/unregistered,较窄数量限额允许;非hash存储键在调用前拒绝;缩小文件数/总字节后builder报invalid且fake HTTP请求计数为0。只静态复核,本轮未跑。", - "evidence": [ - "Full source/fixture review: artifacts/evidence/v027-host-prompt-account-contract-review.json", - "Referenced broker/policy/runtime behaviors remain separately tested in existing scoped evidence; no new test success implied." - ] - }, - { - "path": "backend/internal/service/plugin_prompt_request_context.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "32a967148b2aa0b7a688428654e75eec27fda0546da3cc446d3f46b64941ea82", - "review_fingerprint": "32a967148b2aa0b7a688428654e75eec27fda0546da3cc446d3f46b64941ea82", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "唯一helper优先复用真实Gin Request.Context,将客户端/策略取消传入prompt规划;无Request的纯调用才使用Background。无全局状态、权限扩展或自行出站。", - "evidence": [ - "Full source/fixture review: artifacts/evidence/v027-host-prompt-account-contract-review.json", - "Referenced broker/policy/runtime behaviors remain separately tested in existing scoped evidence; no new test success implied." - ] - }, - { - "path": "backend/internal/service/plugin_prompt_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f71304b91be65081644b6b4aad7362d47dca677b5125c483a9df9459616fc233", - "review_fingerprint": "f71304b91be65081644b6b4aad7362d47dca677b5125c483a9df9459616fc233", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文读取三项断言:超过RPC限额的客户history留宿主且策略载荷不含history,返回本地合并保持原大input;已取消请求context传入invoker并映射不可用;只有结果metadata却没有原验证snapshot的retry失败关闭。未重跑或当作新的模型行为证明。", - "evidence": [ - "Full source/fixture review: artifacts/evidence/v027-host-prompt-account-contract-review.json", - "Referenced broker/policy/runtime behaviors remain separately tested in existing scoped evidence; no new test success implied." - ] - }, - { - "path": "backend/internal/service/plugin_provider.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "94d7f27ef5fa02d1bbb26c0ff8db1cbaceb6e36762560189406507b27c2779a7", - "review_fingerprint": "94d7f27ef5fa02d1bbb26c0ff8db1cbaceb6e36762560189406507b27c2779a7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Full-file review: application composition registers the real plugin manager; disabling the catalog provider removes it rather than choosing an embedded catalog.", - "evidence": [ - "Read all 31 lines. ProvidePluginManager attaches host quota/activity/traffic/account-directory dependencies and installs the manager as catalog resolver/operation invoker before serving.", - "ConfigureProcessExtensionServices(catalog=nil) stores nil in processExtensionCatalog; operations are handled independently. There is no production import of modelpolicy/catalog here.", - "In-process independent modules remain test fixtures only, not production fallback behavior. No code change was necessary." - ] - }, - { - "path": "backend/internal/service/plugin_reconcile_update_registry_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "60ba41c2ca0367b053818977667ba5d38cd75caa0831e62e8b38b985ea89428b", - "review_fingerprint": "60ba41c2ca0367b053818977667ba5d38cd75caa0831e62e8b38b985ea89428b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New in-memory regressions show the promoted-target/pre-drain-peer snapshot passes while a new peer read rejects disabled dependency or operation collision; post-promotion read failure preserves unavailable registry state; no-promotion path performs no extra read. This verifies the helper and static reconcile call-site association, not real candidate-process promotion.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Actual targeted execution is recorded in verification below." - ] - }, - { - "path": "backend/internal/service/plugin_request.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "f1f7d496bd188ae31c81c5194d3a826a69a46509847dc18cfd2a207aae9735dd", - "review_fingerprint": "f1f7d496bd188ae31c81c5194d3a826a69a46509847dc18cfd2a207aae9735dd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Header injection selects only declared or legacy inject hooks that admit the actual account ID, and passes that same ID in the invocation separately from metadata payload. It validates all returned names/values against protected authentication, routing and framing headers on a clone before applying atomically. Request bodies and credentials do not enter the policy payload. Read-only installation/config helpers return a copied config snapshot.", - "evidence": [ - "ApplyRequestHeaders now uses pluginHasInvocationCapability for owner selection and invocation; 0/50/100-percent tests plus unchanged protected-header and named-operation tests passed.", - "artifacts/evidence/v027-broker-and-request-scope-review.json" - ] - }, - { - "path": "backend/internal/service/plugin_request_scope_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b500a1ba3b258f205532775090cf11eee1cb0e3a8e3a1f134ea72241137db60f", - "review_fingerprint": "b500a1ba3b258f205532775090cf11eee1cb0e3a8e3a1f134ea72241137db60f", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "At 0, 50 and 100 percent, two stable account cohorts must receive either no invocation/header change or one invocation with the exact actual AccountID. Host Authorization remains intact. Scheduler tests require only included accounts to obey missing-ticket denial and only included accounts to be blocked by a failed runtime.", - "evidence": [ - "Both top-level cases actually failed before the production fix and passed afterwards; the fixture stubs only the local process RPC boundary and sends no model/network requests.", - "artifacts/evidence/v027-broker-and-request-scope-review.json" - ] - }, - { - "path": "backend/internal/service/plugin_resources.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "e92fe43218bdaf7ce2cb4a4f413f6bb56286bcb5d3b25af700eea63d86b5b89a", - "review_fingerprint": "e92fe43218bdaf7ce2cb4a4f413f6bb56286bcb5d3b25af700eea63d86b5b89a", - "review_status": "pending" - }, - { - "path": "backend/internal/service/plugin_resources_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "914a3f748e0446ae5a4c757127a53d30accb947215b085259c35e20be447aa63", - "review_fingerprint": "914a3f748e0446ae5a4c757127a53d30accb947215b085259c35e20be447aa63", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Actual fixtures assert role filtering, declared grants and package identity; persisted disable rejects despite a stale registry. Global resource availability and contributions require full wildcard/100-percent scope. Explicit account selections verify authoritative identity/type/cohort, fixed filtered scope is only host-declared, and retained job resources work disabled but cannot invent another declared grant. Tests were read, not rerun because their code was unchanged.", - "evidence": [ - "Five complete test bodies and assertions reviewed; this is not evidence that every distributed lifecycle race in plugin_resources.go has been closed.", - "artifacts/evidence/v027-broker-and-request-scope-review.json" - ] - }, - { - "path": "backend/internal/service/plugin_runtime.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "026f99d827fddd0b60f4dcc4baaef963ccb4b2f766920cc3f444e50ea175e2cd", - "review_fingerprint": "026f99d827fddd0b60f4dcc4baaef963ccb4b2f766920cc3f444e50ea175e2cd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "单个插件进程的运行时封装(585 行;上游 aea725f 已有 487 行版本,git diff -U0 共 159 行差异)。上游只承载 OpenAI OAuth 出站转发:用 go-plugin SecureConfig 按清单 sha256 校验二进制、SkipHostEnv 不继承宿主环境、丢弃插件 stdout/stderr、GetInfo 核对插件 ID/版本/协议版本与已校验清单一致、启动健康检查、Forward 流式转发并把错误码清洗成受限字符集。下游在此之上加入扩展宿主能力:同一 gRPC 连接上建立 extensionv1.Client;宿主服务握手 offerPluginHostServices 改为返回错误并注册 AdditionalServiceRegistrar 服务,声明 ExtensionAPI 的插件握手失败即 kill 并拒绝启动(上游是尽力而为只记日志);配置流程拆成 validateNormalizedConfig(插件规范化结果仍受 4MiB/有效 JSON 对象约束)与 applyNormalizedConfig(内容未变则跳过;置 configuring、取消策略上下文、对声明 scheduling 能力的插件读取并校验 describe 契约、保存配置快照、递增 configRevision、清空 catalogCache 及其计数);beginRequest 在 configuring 期间也拒绝新请求;kill 以 killOnce 幂等并释放 generation 租约;observeLease 在租约已丢失时立即 kill 并返回 ErrPluginRuntimeLeaseLost,否则用 watchPluginRuntimeLease 在丢失时 kill。全部是通用进程宿主机制,无任何插件域的业务规则,归 core-extension-and-job-host。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S57-plugin-manager-T1-review.json", - "Read L1-L300 and L301-L585; delta read as git diff -U0 aea725f (159 lines, upstream blob eac0d7f0e, 487 lines) in one piece. Delta hunks: struct fields L30-L51 (extension, scheduling, configSnapshot, configRevision, catalogCache/catalogCacheSize, configuring, policy leases, lease/leaseWatchDone, killOnce); extension client L98; mandatory host-service handshake for extension plugins L123-L126; offerPluginHostServices error contract L134-L176; validateNormalizedConfig / applyNormalizedConfig split L183-L266 (scheduling describe contract L240-L259, snapshot/revision/cache reset L260-L264); beginRequest configuring guard L303-L313; drain via beginDrain L321-L336; idempotent kill with lease release L338-L351; observeLease L353-L370. roundTrip L372-L453, PluginTransportError L455-L486, body streaming L488-L546, pluginResponseBody L548-L567 and header maps L569-L585 are unchanged from upstream.", - "Integrity and isolation checks read: BinarySHA256 decoded and enforced through hcplugin SecureConfig L57-L71; SkipHostEnv L76; null logger and discarded child stdio L72-L74; GetInfo identity cross-check against the verified installation L108-L112; start health check L113-L120; slog lines L166/L168 carry only plugin key and error; PluginTransportError.Error L461-L475 restricts the code to [A-Za-z0-9_.-] (<= 64) and passes the message through sanitizeUpstreamErrorMessage (gemini_messages_compat_service.go L1857).", - "Cancellation and bounds: GetInfo/Health/InitHostServices bounded by startTimeout L101/L154; roundTrip cancels streamCtx on every error path and on body Close L376-L428, L559-L566, and carries the real AccountId/Platform/AccountType L390-L393; catalogCache is cleared on each config apply (L263-L264) and its writers cap it at 2048 entries per runtime (plugin_operation.go L71-L74, model_context_capacity_catalog.go L117-L119, outside this slice).", - "Call chain (rg): beginDrain / cancelPolicyContexts plugin_operation_context.go L144/L135; PluginRuntimeLease, ErrPluginRuntimeLeaseLost, acquirePluginRuntimeLease, watchPluginRuntimeLease plugin_update_contract.go L34/L16/L55/L97; constructed only by PluginManager.newRuntime (plugin_manager.go L1356-L1381, this slice) and by the opt-in process tests in plugin_extension_runtime_test.go.", - "Resolves the plugin_manager.go open point: observeLease kills the runtime and releases the lease itself in its only error branch (L359-L365), so newRuntime's early return leaks nothing.", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/plugin_runtime_lease_loss_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0e5e16853738c9a19386e09f2152916181ba0103d8c255c209022777bff80dc4", - "review_fingerprint": "0e5e16853738c9a19386e09f2152916181ba0103d8c255c209022777bff80dc4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "New observed repository fixture inherits the existing explicit full repository implementation and implements the complete observed lease port. Eight leaf cases prove host-policy plus detached-upstream cancellation while billing remains live, drain-before-runtime cleanup, listener exit on normal release, startup-loss rejection and no weak fallback for error/nil/unobservable/already-lost results.", - "evidence": [ - "artifacts/evidence/v027-astra-runtime-lease-loss-review.json: isolated observed window, exact targeted RUN/PASS, detector/cancellation and normal-release invariants, explicit guarantee limits" - ] - }, - { - "path": "backend/internal/service/plugin_scheduling.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "1d844e2a073e56fcf27f19831bc5544e7950f17b45f81c9aa1284d5014a73331", - "review_fingerprint": "1d844e2a073e56fcf27f19831bc5544e7950f17b45f81c9aa1284d5014a73331", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Scheduler evaluates only scheduling bindings for the actual account's rollout, then uses the running plugin's immutable rules and sanitized account projection without process RPC or credential reads. Shadow exclusions, exact/glob models, identity mismatch, absolute expiry, wildcard constraints and fail-closed unavailable/missing-policy behavior remain unchanged. Out-of-scope accounts are not blocked by a failed plugin.", - "evidence": [ - "SchedulingDecision uses the same stable account cohort predicate as request injection; new synthetic 0/50/100-percent cases cover healthy and missing runtime.", - "artifacts/evidence/v027-broker-and-request-scope-review.json" - ] - }, - { - "path": "backend/internal/service/plugin_security_regression_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9a796ffe441f85b2e7c4446de04cad4f441e6e25b66c571874ca0b213e1637f8", - "review_fingerprint": "9a796ffe441f85b2e7c4446de04cad4f441e6e25b66c571874ca0b213e1637f8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文读UI token/配置/transport安全fixture:token跨实例解密、篡改及其他密文namespace拒绝、包变化不能混资产;repo读失败fail-closed;normalized config验证并只持久化规范结果;已发送或不确定RPC不能重放,stream创建前失败可failover,caller cancellation保留及bounded starting回收。既有测试本轮未重跑。", - "evidence": [ - "Source, red/green and compatibility limits: artifacts/evidence/v027-legacy-extension-port-review.json", - "Full static file read except explicitly partial manager; unchanged tests are not new pass evidence." - ] - }, - { - "path": "backend/internal/service/plugin_theme.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "abe66d249315f708d9e264d9b23df1259d257dc4b9ab96a97f1537fcbacde788", - "review_fingerprint": "abe66d249315f708d9e264d9b23df1259d257dc4b9ab96a97f1537fcbacde788", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文读取公开主题窄适配:URL版本来自完整manifest.Files摘要,读取必须相同revision+规范相对路径;只在当前可用public/theme贡献声明的CSS/font路径内。再调用通用签名UI资产读取并比实际路径与文件SHA;不开放config页/scripts或任意包文件。可见性采用本地注册表/贡献快照,不将其视为业务执行权限证明。", - "evidence": [ - "Full source and boundaries: artifacts/evidence/v027-host-update-theme-completion-review.json", - "Current source/fixture read only; no additional execution implied." - ] - }, - { - "path": "backend/internal/service/plugin_theme_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "acce8b62489c1f259127b9e5799a530b20b64c4c0b6288c4639e809465c37b61", - "review_fingerprint": "acce8b62489c1f259127b9e5799a530b20b64c4c0b6288c4639e809465c37b61", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "Directly impacted public-theme test now verifies global 0/50/100 rollout admission and retains asset declaration/digest checks.", - "evidence": [ - "0% and 50% UI bindings produce no public contribution and ReadPublicThemeAsset rejects the CSS; 100% restores the declared stylesheet/font.", - "The old positive fixture was corrected to explicitly use 100%, rather than relying on an omitted percent=0.", - "Existing private-file/path/revision/digest and disabled-binding assertions run in the same exact test." - ] - }, - { - "path": "backend/internal/service/plugin_ui_session_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5d42987633e38f8facaf5ef1fd2fb359fb7e33dd1ead8fccfdd6adfc7c2cfee4", - "review_fingerprint": "5d42987633e38f8facaf5ef1fd2fb359fb7e33dd1ead8fccfdd6adfc7c2cfee4", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Role/entrypoint tests reject undeclared or admin-to-user escalation and constrain administrator browsing of user pages to a user bridge. Config sessions are explicitly tested with empty/disabled bindings and error state; business sessions reject missing/unrelated capability, and AllAccounts requires both wildcard dimensions and 100-percent rollout. Existing static tokens survive disable/config/runtime revision with unchanged package identity. Manifest test requires contributed UI in signed assets.", - "evidence": [ - "v027-ui-session-admission-agent-review.json parent_verified: four exact new top-level tests and all global-binding subcases actually RUN/PASS; prior broad selector mismatch is explicitly corrected.", - "Entire file assertions and fixture roles read; previous PageSession results reused, not rerun. This does not close plugin_manager.go." - ] - }, - { - "path": "backend/internal/service/plugin_update.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "0a9486675eb5b02d94e2d9afd18896872fbe3353f3e3bccf04826e762c8f02c8", - "review_fingerprint": "0a9486675eb5b02d94e2d9afd18896872fbe3353f3e3bccf04826e762c8f02c8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整读更新协调器。先安装签名候选检查身份/兼容/不变版本与读时revision/package;同包重试幂等,同版本不同内容拒绝。候选用无业务Host端口做配置规范化验证/健康检查,不Apply或领取任务;stage前后两次预检保留当前绑定/配置。仅目标runtime排空,持久pending包可重启续作,最终由仓库SSI与generation CAS提交;waiting/state conflict不伪成功,候选失败清独有临时目录。explicit follow-bundled查精确宿主lock、basename路径、包SHA/ID/version后切换模式,允许明确降回内置但不回滚业务数据。", - "evidence": [ - "Full source and boundaries: artifacts/evidence/v027-host-update-theme-completion-review.json", - "Earlier precise update/bootstrap/SSI proof: v027-astra-update-admission-review.json, v027-astra-update-persistence-review.json, v027-astra-bootstrap-update-review.json, v027-astra-registry-atomicity-design.json" - ] - }, - { - "path": "backend/internal/service/plugin_update_contract.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "98eaa00ec181cc5a5a0fc42a50cc3833b589e59eec4d92e7884c22fdfafa4ae4", - "review_fingerprint": "98eaa00ec181cc5a5a0fc42a50cc3833b589e59eec4d92e7884c22fdfafa4ae4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文读版本更新/租约/执行代次端口与replacement binding。优先observable locker,出错或nil/Done不完整不能退回弱接口;已失联即时拒绝并释放,正常释放Err=nil不误报。私有context承载execution/revision/business purpose,不能从UI载荷提升权限。替换只精确保留旧三元能力scope的enabled/rollout,新声明默认disabled;没有删数据/自动回滚实现。", - "evidence": [ - "artifacts/evidence/v027-astra-runtime-lease-loss-review.json", - "artifacts/evidence/v027-astra-update-persistence-review.json", - "Full current file read in parent review; not merely symbol or filename classification." - ] - }, - { - "path": "backend/internal/service/plugin_update_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cee17f17103bae0cefc0e5a78d50215554fcb18a27556619987dd9293a27982a", - "review_fingerprint": "cee17f17103bae0cefc0e5a78d50215554fcb18a27556619987dd9293a27982a", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "Signed test packages verify repeated identical upload is read-only, changed content at the same version and invalid signatures reject, and stale revision does not replace the installation. Config-CAS conflict must not apply config or cancel existing work. The corrected resume fixture implements the complete update interface and now proves real startup failure. Fresh registry fixtures exercise stage/resume/new-manager rejection for dependency, ownership and read drift while preserving pending/old files, plus administrator disable and new-capability defaults.", - "evidence": [ - "v027-astra-update-admission-review.json includes ten actual admission leaf RUN/PASS outcomes; full fixture implements PluginUpdateRepository and counts List, stage, pending read and commit calls.", - "Parent exact resume test observed RUN/PASS after requiring startup-specific error and one pending read; successful candidate health/config validation and real promotion are not claimed.", - "Full test file was read; prior unchanged signature/config tests were not rerun." - ] - }, - { - "path": "backend/internal/service/pricing_named_family_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5953175f48d258f204e201db14173c26d80b12c275570d10d1662c335333d1ce", - "review_fingerprint": "5953175f48d258f204e201db14173c26d80b12c275570d10d1662c335333d1ce", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(上游无此文件),证明 GetModelPricing 对 GPT-5.6 命名系列的取价优先级修复:目录只有泛化 gpt-5.6 条目时,sol/terra/luna 命名系列的静态兜底价必须先于泛化价生效(L9-L32,含 models/ 前缀与 -ssvip 变体);目录存在精确条目或系列条目时按 精确 > 系列 > 泛化 取用,且 gpt-5.6-lunatic-project 这类部分重名不得冒认 luna 系列(L34-L47)。对应 pricing_service.go matchOpenAIModel 中下游新增的命名系列前置循环,防止 Luna(价低 25 倍)与 Sol/Terra 共享泛化价的计费错误。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "47 行全读;TestPricingNamedGPT56FamilyPrecedesGenericFallback 用 require.InDelta 逐系列核对 input/output/cache 写读四价,TestPricingNamedGPT56FamilyPreservesExplicitCatalogPrices 用 require.Same 证明目录条目身份不被兜底覆盖。", - "git ls-tree aea725f 无此路径,整文件即下游 delta;被测代码为 pricing_service.go L1468-L1487(gpt-5.6-sol/terra/luna 循环)与 openAIGPT56*FallbackPricing 静态价(L78-L119)。", - "No test execution; the assertions were verified by reading only." - ] - }, - { - "path": "backend/internal/service/pricing_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e408f46c029e1ab884d7691c6e94bc5aee537ec572e9ad940317869d09287ff7", - "review_fingerprint": "e408f46c029e1ab884d7691c6e94bc5aee537ec572e9ad940317869d09287ff7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "LiteLLM 目录驱动的宿主计价服务:远程下载/哈希同步、fallback+override 双层叠加与热重载指纹、above_XXXk 绝对价折算长上下文阶梯(含单侧阶梯与孤儿 cache 档哨兵告警)、Claude 系列有序匹配、OpenAI 回退链。下游相对上游 aea725f 仅 +29/-1:LiteLLMModelPricing 增加 deepseekIdentity 指针字段、buildPricingData 末段接入 mergeDeepSeekPricing、GetModelPricing 与 GetIdentifiedModelPricing 前置 lookupDeepseekPricingLocked 短路、matchOpenAIModel 增加 gpt-5.6-sol/terra/luna 命名系列先于数字回退的取价循环。这些都是宿主计价管线的通用机制接入,未发现插件侧重复执行体。仅静态阅读,未执行任何构建或测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "1667 行全读;diff 锚点:L139 deepseekIdentity 字段、L960-L961 buildPricingData 注释改写、L973 mergeDeepSeekPricing 调用、L1141-L1143 与 L1219-L1221 lookupDeepseekPricingLocked 短路、L1468-L1487 命名系列循环(目录条目优先于静态兜底)。", - "调用链:lookupDeepseekPricingLocked/mergeDeepSeekPricing 定义于 service/deepseek_pricing.go(两个调用点均持 s.mu 读锁;merge 在官方卡之上重放 override 条目,与 buildPricingData 的层序一致);GetModelPricing/GetIdentifiedModelPricing 消费方含 billing_service.go、gateway_usage_billing.go、model_pricing_resolver.go、model_plaza_service.go。", - "No production behavior edit, no test execution; long-context ladder and override semantics were verified by reading only." - ] - }, - { - "path": "backend/internal/service/profit_control_dormant_regression_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "76e5018b57dd14818030ccd2cb8af9f8d15b93402e8b1f330f6de3b5beb13519", - "review_fingerprint": "76e5018b57dd14818030ccd2cb8af9f8d15b93402e8b1f330f6de3b5beb13519", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "真实 SchedulerSnapshotService 配合内存 GroupRepository,及 canonical 边界清门回归;不同于 auth/billing group 的已启用历史 group 仍原样投影,但不再触发第二次读/建门;pricingAt、倍率和源对象不变。私有手造门仍产生原数学 veto,而 request/turn/gateway 清门,runtime-origin selection 不携门。", - "evidence": [ - "Full source/diff review and exact test selectors: artifacts/evidence/v027-astra-dormant-profit-review.json", - "Canonical request/turn/gateway boundaries remain dormant; old columns, saved multipliers, pricingAt and private arithmetic are retained. No model requests or live data reads." - ] - }, - { - "path": "backend/internal/service/profit_preview.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": false, - "content_sha256": null, - "deleted_upstream_blob": "d63b9317cecf996c9ceb5e74adadb968f50031b7", - "review_fingerprint": "3b460f7e87251680519b13b949a83989585c291f24561abc1b3ef5eaf81cd421", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "基于账户U、收费D、peak与最小user override计算阈值/模型准入数量,输出manual/probe warning;用于CLI预览而非真实usage结算。 预览服务按历史决定退休且独立数据schema仍保留;本轮不恢复它或用它读生产数据。", - "evidence": [ - "Exact deleted blob and replacement assertion mapping: artifacts/evidence/v027-astra-deleted-path-review.json", - "该已删文件及旧profit-preview均未运行;独立dormant证据记录限定服务回归。", - "Deletion basis: 5f216d1d07f091b8942aa70e3c5ee3d7fc4153fe", - "The bound dormant implementation is included with this review; its exact eight source SHA256 values were verified before import." - ] - }, - { - "path": "backend/internal/service/profit_preview_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": false, - "content_sha256": null, - "deleted_upstream_blob": "1030ef41aa09efada0d575dd4766ce809d07205f", - "review_fingerprint": "dbb6671e8c0d9b5e9000a05d09befdd0d9ea454b0579c9bd442f7ac04a2e9f1c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "验证account倍率而非probe倍率决定准入、epsilon边界、零admitted模型统计、assume-enabled及五平台行为。 与preview服务一致继续删除;不得把本轮通过计数当作旧预览所有断言仍被覆盖。", - "evidence": [ - "Exact deleted blob and replacement assertion mapping: artifacts/evidence/v027-astra-deleted-path-review.json", - "该已删文件及旧profit-preview均未运行;独立dormant证据记录限定服务回归。", - "Deletion basis: 5f216d1d07f091b8942aa70e3c5ee3d7fc4153fe", - "The bound dormant implementation is included with this review; its exact eight source SHA256 values were verified before import." - ] - }, - { - "path": "backend/internal/service/prompt_domain_runtime.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ebe334c1efac3ef6e6de10cf90cc81189c1df90fc61403913189006434efa536", - "review_fingerprint": "ebe334c1efac3ef6e6de10cf90cc81189c1df90fc61403913189006434efa536", - "review_status": "pending" - }, - { - "path": "backend/internal/service/prompt_domain_runtime_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "afb76305aa3a8f7cb7b861ce96ca1037a240332057fac7cbaab30ade34781fcb", - "review_fingerprint": "afb76305aa3a8f7cb7b861ce96ca1037a240332057fac7cbaab30ade34781fcb", - "review_status": "pending" - }, - { - "path": "backend/internal/service/provider_identity.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "07bf1c8d71ab8a571615de1abf045ebaa1e9f25ff3c3a5adb087479b44c20cd2", - "review_fingerprint": "07bf1c8d71ab8a571615de1abf045ebaa1e9f25ff3c3a5adb087479b44c20cd2", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "下游新增文件:provider 身份三元组(platform/wire_platform/provider_profile)的解析与隔离门。ResolveAccountProviderIdentity 把 cindy 账号钉死为 openai 线协议 + cindy_laxa_v1 档,且要求 API key 与精确 https://api.laxarouter.ai 根地址(L19-L31,legacy openai+laxa 行明确留给迁移 229 做一次性投影);ProviderIdentityCompatible 要求三轴全等、共享线协议也不许跨档回退(L96-L105);validateProviderIdentityAccountsForGroup/GroupBindings 在 admin 绑定入口双向拦截 cindy 账号与 composite 组互绑(L124-L180)。三轴比较门是宿主调度/绑定机制,但文件内写死的规则实体全部服务于 cindy 供应商的接入隔离,故按 cindy-provider 的宿主胶水归属。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "180 行全读;git ls-tree aea725f 无此路径,整文件为下游 delta。锚点:WirePlatformOpenAI/ProviderProfileCindyLaxaV1 常量(L10-L13)、Account/Group 的 EffectiveWirePlatform 与 EffectiveProviderProfile 回退推导(L44-L94)、hasCanonicalCindyProviderIdentity(L107-L113)。", - "调用链(rg):admin_account.go L493/L637/L788/L975/L1182、admin_group.go L393/L644/L797/L1083、handler/admin/account_handler.go L218、handler/admin/account_job_execution.go L312、repository/group_repo_cindy_split.go L166、image_studio_job_service.go L99/L161;IsCindyAPIKeyAccount 定义于 service/cindy_identity.go——未见插件内第二执行体。", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/provider_identity_admin_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8b59ba1a5ab8ac2a6633c41c9037f0bf13af5f550907a4cfaf8ba9ee8e7919ba", - "review_fingerprint": "8b59ba1a5ab8ac2a6633c41c9037f0bf13af5f550907a4cfaf8ba9ee8e7919ba", - "review_status": "pending" - }, - { - "path": "backend/internal/service/provider_identity_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "d83ac391974f14d276c60a91664a8bd43fe5af2c7d12fa69d1d1dd4bfe7bd473", - "review_fingerprint": "d83ac391974f14d276c60a91664a8bd43fe5af2c7d12fa69d1d1dd4bfe7bd473", - "review_status": "reviewed", - "decision": "adapter", - "owner": "cindy-provider", - "reason": "下游新增单元测试,覆盖 provider_identity.go 的四个门:ResolveAccountProviderIdentity 只接受一等 cindy(精确根地址 + API key;带 /v1 路径或 OAuth 报错;legacy openai+laxa 维持普通 openai;Kimi 等自适应平台保留自身身份)(L23-L90);ProviderIdentityCompatible 三轴任一不等即 false(L92-L119);validateProviderIdentityGroupBindings 把 cindy 排除出 composite 组而普通 openai 可绑(L121-L139);调度侧 isOpenAICompatibleAccountEligibleForRequestBeforeProfit 要求 canonical 三轴、wire 或 profile 漂移即不可调度(L141-L178)。证明 cindy 身份隔离在解析、绑定、调度三层一致。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "178 行全读;git ls-tree aea725f 无此路径,整文件为下游 delta。锚点:providerIdentityGroupRepoStub(L10-L21)、表驱动用例 legacy exact laxa remains ordinary openai at runtime(L34-L41)、cindy requires exact root(L59-L65)。", - "调度断言的被测函数 isOpenAICompatibleAccountEligibleForRequestBeforeProfit 与 NormalizeOpenAICompatiblePlatform 位于 service 包调度路径(gateway 账号筛选),测试证明其与 ProviderIdentityCompatible 同轴。", - "No test execution; statically read only." - ] - }, - { - "path": "backend/internal/service/quota_activity.go", - "candidate_owner": "core-quota-and-protocol", - "role": "source", - "present": true, - "content_sha256": "d9c2ff9e729671b3a3055b0085d6e4f4c5c16dcb9f453bd2b496ac6c911c442c", - "review_fingerprint": "d9c2ff9e729671b3a3055b0085d6e4f4c5c16dcb9f453bd2b496ac6c911c442c", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "QuotaActivity wraps request traces, queued usage tasks, persisted/failed log receipts, heartbeat refresh, and uncertain-state fencing so a late or dropped bill prevents a new calibration pair.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=d9c2ff9e729671b3a3055b0085d6e4f4c5c16dcb9f453bd2b496ac6c911c442c; current_sha256=d9c2ff9e729671b3a3055b0085d6e4f4c5c16dcb9f453bd2b496ac6c911c442c; inventory_sha256_match=true", - "lines 99-148: Attach/ObserveQuotaAccount starts per-account activity", - "lines 179-215: TrackQuotaUsageTask registers pending work before queue submission and marks missing receipts as gaps", - "lines 224-270: request close waits for queued tasks and heartbeats active observations", - "lines 274-296: Read fails closed on uncertain/dirty activity", - "callers: gateway_handler.go:2677-2708; gateway_usage_billing.go:567-605" - ] - }, - { - "path": "backend/internal/service/quota_activity_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "905606dc72d1767bd163f59e3166b6858a0ce373a66c88b3465f153360f18aef", - "review_fingerprint": "905606dc72d1767bd163f59e3166b6858a0ce373a66c88b3465f153360f18aef", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static tests cover queued usage completion, dropped usage invalidation, and a later dropped bill after an earlier success; test execution was not repeated.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=905606dc72d1767bd163f59e3166b6858a0ce373a66c88b3465f153360f18aef; current_sha256=905606dc72d1767bd163f59e3166b6858a0ce373a66c88b3465f153360f18aef; inventory_sha256_match=true", - "TestQuotaActivityWaitsForQueuedUsageAfterRequestEnds", - "TestQuotaActivityDroppedUsageInvalidatesCalibration", - "TestQuotaActivityOneSuccessfulTurnDoesNotHideLaterDroppedBill" - ] - }, - { - "path": "backend/internal/service/quota_estimate.go", - "candidate_owner": "core-quota-and-protocol", - "role": "source", - "present": true, - "content_sha256": "d9f4ae74a47693cb7a5f54e6f127fc3d4680654c770b7e447ecc2ed52adcd152", - "review_fingerprint": "d9f4ae74a47693cb7a5f54e6f127fc3d4680654c770b7e447ecc2ed52adcd152", - "review_status": "pending" - }, - { - "path": "backend/internal/service/quota_estimate_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5e56f083dce954cea3d06c8e8c70666907a3836a97a4aebe57a90c53d09a7e87", - "review_fingerprint": "5e56f083dce954cea3d06c8e8c70666907a3836a97a4aebe57a90c53d09a7e87", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static tests cover imported-consumption cancellation at the math layer, mismatched owner/period, late observation, invalid cost, reset/expiry, and value-based identity; test execution was not repeated.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=5e56f083dce954cea3d06c8e8c70666907a3836a97a4aebe57a90c53d09a7e87; current_sha256=5e56f083dce954cea3d06c8e8c70666907a3836a97a4aebe57a90c53d09a7e87; inventory_sha256_match=true", - "TestQuotaEstimateIgnoresImportedConsumption lines 11-24", - "TestQuotaEstimateRejectsUnpairedAndResetObservations lines 27-59", - "TestQuotaEstimateIdentityUsesValueNotPointerAddress lines 61-69" - ] - }, - { - "path": "backend/internal/service/quota_measurement_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b89e8d26541227d3c57ed19b01174fdb0642f44e547ae10085b87254f8e98f83", - "review_fingerprint": "b89e8d26541227d3c57ed19b01174fdb0642f44e547ae10085b87254f8e98f83", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static tests cover Spark additional-rate-limit selection and parent billing identity, in-flight usage-log rejection, dropped activity, and a clean follow-up observation; test execution was not repeated.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=b89e8d26541227d3c57ed19b01174fdb0642f44e547ae10085b87254f8e98f83; current_sha256=b89e8d26541227d3c57ed19b01174fdb0642f44e547ae10085b87254f8e98f83; inventory_sha256_match=true", - "TestQuotaMeasurementUsesShadowWindowAndParentBillingIdentity lines 25-49", - "TestQuotaMeasurementRejectsInFlightAndLateBills lines 62-91" - ] - }, - { - "path": "backend/internal/service/ratelimit_service.go", - "candidate_owner": "core-quota-and-protocol", - "role": "source", - "present": true, - "content_sha256": "999d22f39196760c1b359b0618234aec3c319a0d1b482168551fbfbba49b7859", - "review_fingerprint": "999d22f39196760c1b359b0618234aec3c319a0d1b482168551fbfbba49b7859", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 429 classification preserves unknown reset times, recognizes 30-day hard quota without inventing a deadline, skips global header persistence for Spark shadows, and writes Spark quota exhaustion into a model-scoped limit.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=999d22f39196760c1b359b0618234aec3c319a0d1b482168551fbfbba49b7859; current_sha256=999d22f39196760c1b359b0618234aec3c319a0d1b482168551fbfbba49b7859; inventory_sha256_match=true", - "lines 1793-1813: response-header Codex snapshots are skipped for shadow accounts", - "lines 2358-2392: Spark 429 requires OAuth/Spark model, uses long reset only for explicit quota windows, and writes model_rate_limits", - "openai_oauth_429_classifier.go:20-82: 5h/7d/30d and unknown reset classification", - "ratelimit_service_openai_test.go:321-357: Spark shadow isolation assertions" - ] - }, - { - "path": "backend/internal/service/ratelimit_service_403_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "47d604b0d65d6a775440706b22ca6ab4e3b5c22c9623ec444430d319eb8ceb7d", - "review_fingerprint": "47d604b0d65d6a775440706b22ca6ab4e3b5c22c9623ec444430d319eb8ceb7d", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static 403/rate-limit test fixture was checked for account-wide error-path coverage; no quota conclusion beyond the named fixture was made and tests were not rerun.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=47d604b0d65d6a775440706b22ca6ab4e3b5c22c9623ec444430d319eb8ceb7d; current_sha256=47d604b0d65d6a775440706b22ca6ab4e3b5c22c9623ec444430d319eb8ceb7d; inventory_sha256_match=true", - "current file SHA only; 403 path is outside the primary quota-window assertions" - ] - }, - { - "path": "backend/internal/service/ratelimit_service_anthropic_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ba6a162663fbd5741abb98450b830dec8c994ac7483803aef8a0c2e3874f19d8", - "review_fingerprint": "ba6a162663fbd5741abb98450b830dec8c994ac7483803aef8a0c2e3874f19d8", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "This candidate is quota-owner classified but covers Anthropic windows rather than ordinary OpenAI/Spark quota; retained as reviewed scope context, not as evidence for OpenAI behavior.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=ba6a162663fbd5741abb98450b830dec8c994ac7483803aef8a0c2e3874f19d8; current_sha256=ba6a162663fbd5741abb98450b830dec8c994ac7483803aef8a0c2e3874f19d8; inventory_sha256_match=true", - "current file SHA only; OpenAI quota conclusions use account_quota_windows_test.go and ratelimit_service_openai_test.go" - ] - }, - { - "path": "backend/internal/service/ratelimit_service_cindy_balance_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "048a9d8b222dc6e1267ef00d02c62205cd4b7984044e430293b4332c94bcb3e3", - "review_fingerprint": "048a9d8b222dc6e1267ef00d02c62205cd4b7984044e430293b4332c94bcb3e3", - "review_status": "pending" - }, - { - "path": "backend/internal/service/ratelimit_service_openai_image_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6f9830f711ff8d7d87850ee48448d87a3b6f734985977d700741b3487ae94b55", - "review_fingerprint": "6f9830f711ff8d7d87850ee48448d87a3b6f734985977d700741b3487ae94b55", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static test source covers OpenAI image model-scoped cooldown separation; it supports model-scope mechanics but not the Spark quota window itself. Tests were not rerun.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=6f9830f711ff8d7d87850ee48448d87a3b6f734985977d700741b3487ae94b55; current_sha256=6f9830f711ff8d7d87850ee48448d87a3b6f734985977d700741b3487ae94b55; inventory_sha256_match=true", - "current file SHA only", - "model-scoped image limit path shares model_rate_limits infrastructure" - ] - }, - { - "path": "backend/internal/service/ratelimit_service_openai_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b2885b87f2a9a47f2383adfb3db6bfd5b14e7ba3793adda369d6b9e1e8e6948b", - "review_fingerprint": "b2885b87f2a9a47f2383adfb3db6bfd5b14e7ba3793adda369d6b9e1e8e6948b", - "review_status": "pending" - }, - { - "path": "backend/internal/service/ratelimit_session_window_test.go", - "candidate_owner": "core-quota-and-protocol", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f323590c083392a36c335fa2fa49bb281ea266020144cb6ce5563d6d4ea6c6e8", - "review_fingerprint": "f323590c083392a36c335fa2fa49bb281ea266020144cb6ce5563d6d4ea6c6e8", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "Static session-window fixture was checked for neighboring cooldown behavior; it does not prove the OpenAI quota-estimate path and tests were not rerun.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=f323590c083392a36c335fa2fa49bb281ea266020144cb6ce5563d6d4ea6c6e8; current_sha256=f323590c083392a36c335fa2fa49bb281ea266020144cb6ce5563d6d4ea6c6e8; inventory_sha256_match=true", - "current file SHA only; no direct account_quota_estimates or Spark assertion" - ] - }, - { - "path": "backend/internal/service/reasoning_fidelity_control_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5fc2ca9347dfbb1d9732364946e5ac59a31e7f294ecc6eecfeb5c175cb3f8c10", - "review_fingerprint": "5fc2ca9347dfbb1d9732364946e5ac59a31e7f294ecc6eecfeb5c175cb3f8c10", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增、//go:build reasoning_fidelity 门控的离线控制测试,静态阅读证明诊断 harness 的安全性质:每 slot 单次发送(含 DoWithTLS 重试被拦、before_send 只出现一次)、deny/来源变更/伪造 grant/预算耗尽/已取消 ctx 一律零网络调用、broker 输出不泄露 api_key 与上游主机名;分离 cancel 的 Forward 重新获得实验 deadline 且关闭后释放;bootstrap 精确校验账号/组/台账(重复 slot 拒绝);工具回放保持原始输出顺序/phase/未知字段、约束不重复、incomplete 不回放;离线假上游可走通真实 Forward;组 effort 策略在 gateway 与 direct 两臂前各恰好应用一次且两臂拿到相同生效 reasoning。仅静态阅读,未执行(也不可在 CI 执行)。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: budget single-send + TLS block + leak check L78-L97, deny/source/bad-grant/cancel zero-calls L98-L136, detached ctx deadline L137-L153, bootstrap/ledger exactness L154-L168, tool replay raw preservation L169-L194, offline real Forward L195-L212, one-shot group policy for both arms L213-L245.", - "Build tag reasoning_fidelity keeps the whole cluster out of normal builds and CI test runs; subject is the diagnostic harness in reasoning_fidelity_live/support, not production behavior.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/reasoning_fidelity_live_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "744adc7e65e7b1a20d6e56116c5f9a6a46b453667fbe9e45b69638197a94e8d7", - "review_fingerprint": "744adc7e65e7b1a20d6e56116c5f9a6a46b453667fbe9e45b69638197a94e8d7", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增的受控在线探针 harness(reasoning fidelity A/B):双重门控(build tag + SUB2API_REASONING_FIDELITY_LIVE=1),经 stdin/stdout JSON-line broker 协议运行;bootstrap 严格校验固定账号(ID 15522、名称『白嫖666』、APIKey、组成员、代理一致性)与预算台账(24 次/45 分钟/8MiB、slot 去重);每 slot 发送前必须获得 broker grant(slot/指纹/attempt/elapsed 全比对),出站边界哈希校验 endpoint/Authorization/账号 JSON/代理,禁用重定向并清 GetBody,重试逃逸即计 blocked;401/403 与 402/429 立即停批;输出只含 SHA-256 摘要(答案/响应体/ID/模型/effort),并观察 input/reasoning/model 是否被网关改写;after 阶段按资格(无服务端上下文、无 compaction、模型与 effort 摘要一致、答错或 518 token 候选)构造 pilot 回放。静态阅读,绝未执行或联网。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: opt-in gate + stdout silencing L146-L176, bootstrap validation L246-L289, broker grant + source verification + single-send budget L704-L797 (redirects disabled, GetBody nil L775-L777), stop conditions L449-L458, digest-only result fields L80-L117/L478-L503, pilot eligibility/body L585-L628, deadline reattachment for detached Forward L762-L777, bounded response capture L799-L831.", - "Consumes only exported-for-test wiring from reasoning_fidelity_support_test.go and the production repository.NewHTTPUpstream; no plugin logic duplicated. Fixed account name/id are pins for a user-owned diagnostic account, no credentials in file.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/reasoning_fidelity_parse_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f2dd68944601c223247b82942278b1196f9fc323c6de7aa8d8f20a469b9bb5ca", - "review_fingerprint": "f2dd68944601c223247b82942278b1196f9fc323c6de7aa8d8f20a469b9bb5ca", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增:诊断用严格 Responses 解析器及其自校验。fidelityParseResponse 绝不把部分响应当 completed:需要显式终端证据(JSON status 或 SSE response.completed/failed/incomplete),SSE 支持 LF/CRLF/CR、announced 项必须完成、终端后再有内容即 parse 错、重复键/尾随 JSON 拒绝、usage 缺失不补零且 token 必须非负整数;final_answer phase 优先、reasoning/commentary 不进入评分文本;错误分类只认结构化 code(auth/quota/rate_limit),数字码与 message 文案不算;fixture 真值由测试内独立穷举复核(排列 25/ABCDFE/CBEADF,订单 ABE/11/36),评分要求恰好三字段 JSON(允许 ``` 与 ```json 围栏)。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: prompts/fixtures without answers L20-L24, strict parse core L54-L109, SSE state machine with announced-item accounting L206-L411, item identity rule L415-L437, phase-aware text extraction L463-L554, structured error classes L556-L580, duplicate-key/trailing rejection L588-L620, scoring L622-L661, independent truth enumerations L663-L729, strict terminal/usage matrices L829-L922.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/reasoning_fidelity_support_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "c43181344919028ec63f93413da73bcf8e29c5634e2743803064943c2bab5dbd", - "review_fingerprint": "c43181344919028ec63f93413da73bcf8e29c5634e2743803064943c2bab5dbd", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增、build tag 排除在应用构建之外的 harness 接线:ReasoningFidelityGatewayForTest 只用 cfg+upstream 构造网关,设置来自不可写的冻结快照(Set/Delete 返回错误),business prompt 支持 codex-skill hybrid 配对发布(revision/version/prompt ID 与 SHA-256 交叉校验,不做下载/安装/种子/后台刷新);ReasoningFidelityContextForTest 以合成 APIKey(-1) 重建组策略上下文;ReasoningFidelityDirectRequestForTest 复用 fast policy、业务提示词、access token 与 buildUpstreamRequest,且刻意不重复组 effort 策略(两臂共用入口已应用一次)。不附着任何可写账号/计费/会话仓储。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: gateway constructor with nil repos L28-L37, paired publication validation L38-L57, read-only setting store L67-L107, trusted context reproduction L109-L124, direct request builder avoiding double policy application L126-L155 (comment L132-L135).", - "Package service with build tag: exposes internals to the external service_test harness only; grep confirms no production file imports these helpers.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/reasoning_replay_diagnostic_control_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8e5c3b603366319d230f939f9cd7c37d691da6f7ddbd86b1e16711ee7486fd4e", - "review_fingerprint": "8e5c3b603366319d230f939f9cd7c37d691da6f7ddbd86b1e16711ee7486fd4e", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增、双 build tag 门控的回放诊断离线控制测试:权威终端覆盖裸 SSE 拒绝码(completed/无关 failed 不授权恢复,event-only failed 保留精确 code);单发送与 attempt 证据协议(before_send 与 attempt_result 各一次,broker 输出不含 api_key/主机/响应 ID/答案明文);仅结构化签名拒绝允许恰好一次额外 POST、第三次被拦、私密上游错误文案不外泄;关键词提及/通用码/数字码不得重试;来源变更/预算/取消/authorization 变化在 grant 前失败且零输出;401/403/402/429 停止全部后续;恢复共享原始 deadline 不延长;受控密文腐蚀只改一个 encrypted_content(其余字段与非 reasoning 项字节等价,重复 reasoning 身份拒绝);负缓存 fixture 保留旧+新密文交给真实 store 判定;bootstrap 钉死账号 15522 与合成租户。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: terminal supersession L82-L95, one-send + evidence + leak checks L96-L114, exact-rejection double-attempt cap L115-L134, unproven rejection matrix L135-L146, pre-grant failures L147-L167, auth/quota stop L168-L179, shared deadline L180-L201, bad grant zero-calls L202-L209, controlled cipher corruption invariants L210-L247, negative fixture preserves both ciphers L248-L264, bootstrap identity L265-L274.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/reasoning_replay_diagnostic_live_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "737e0d5ed12d36f8d371f92b11047e5fb02e9a3c0e4e53e011dde3c070c3a423", - "review_fingerprint": "737e0d5ed12d36f8d371f92b11047e5fb02e9a3c0e4e53e011dde3c070c3a423", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增的回放/恢复在线研究 runner:三重门控(reasoning_fidelity 与 reasoning_replay_diagnostic 两个 build tag + SUB2API_REASONING_REPLAY_LIVE=1),run_id 钉死 reasoning-replay-recovery-20260907,预算 16 次;bootstrap 复用 fidelity 校验并额外要求账号 15522、合成 UserID 920000015522、可选 REASONING_REPLAY_SOURCE_SHA 匹配;用 ReasoningReplayDiagnosticAttach 挂接内存 store 后跑真实 Forward/ForwardAsChatCompletions;每案例 slot 上限 1(invalid_cipher/负缓存案例为 2 且第二次必须先观察到结构化签名码);RecoveryObserved 要求恰好两条 attempt 记录且首条为签名码,NegativeCacheObserved 要求单次发送且响应头 X-Sub2API-Reasoning-Recovery=rejected_history_skipped;受控密文腐蚀与负缓存续写体由 control 测试验证的构造器生成;输出仅摘要与保留性布尔(旧密文移除/新密文保留/回放字段保留)。静态阅读,绝未执行或联网。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: gates + run id + budget L30-L31/L119-L146, bootstrap extra pins L147-L155/L164-L166, case plan incl. chat first/final and negative cache L229-L271, recovery/negative observation rules L372-L377, per-case slot cap with signature-code precondition L543-L556, source verification + grant protocol + deadline reattach L557-L646, digest-only attempt records L647-L674, strict SSE error-code extractor reusing production parser L675-L732, bounded capture L734-L759.", - "The only rejection-code knowledge here (replayDiagnosticSignatureCode L540-L542) mirrors the production contract exposed via ReasoningReplayDiagnosticRejectionCode; diagnostic-only, no production executor added.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/reasoning_replay_diagnostic_parse_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "acd2c804b680c8f50124136ba5da10b2bdea08aa1d62a58cdfdd66f063299136", - "review_fingerprint": "acd2c804b680c8f50124136ba5da10b2bdea08aa1d62a58cdfdd66f063299136", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增:诊断用严格 Chat Completions 投影解析器与其测试。信封校验(object 类型、status/type 门、id/model 稳定、usage 各计数非负 int64 且缺失不补零);finish_reason 只认 stop/tool_calls(length/空为 incomplete,其它 failed);assistant 消息检查(禁 legacy function_call、refusal 仅允许空串、reasoning 别名必须是字符串、tool_calls 上限 32、ID 唯一、index 连续、arguments 必须是 JSON 对象);流式合并对未知 delta 键 fail-closed、工具身份必须在参数分片前完整宣布、usage-only 尾包不能修复完成态、[DONE] 后任何数据即失败;续写只回放观察到的原始 assistant 消息 + 工具结果(tool_choice=none),仅精确的 load_orders 空参调用可执行;30+ 失败矩阵与请求契约(模型/effort/stream_options)校验。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: chat body/continuation builders L25-L90 (no constraint duplication, no fabricated call id), envelope/usage validation L127-L180, finish mapping L182-L198, message inspection L214-L264, stream delta merge with fail-closed unknown keys L301-L350 and tool identity ordering L352-L414, SSE assembly + usage-only trailer rule L443-L549, tests: final answer excludes reasoning L568-L583, tool projection continuation invariants L584-L619, strict failure matrix L626-L676, exact-tool-only execution L677-L689, request contract L690-L706.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/reasoning_replay_diagnostic_support_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ed94338b8406bcbf2afc3d7dff192ef200e4b51f361637efb388fcafbe15593c", - "review_fingerprint": "ed94338b8406bcbf2afc3d7dff192ef200e4b51f361637efb388fcafbe15593c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "下游新增、双 build tag 的诊断接线(package service):ReasoningReplayDiagnosticAttach 给网关挂接内存 store,实现生产 GatewayCache+OpenAIReasoningStateStore 接口但更严上限(16 个批次、64 条拒绝记录,另检查 scope/tenant/key 必须是合法 SHA-256 摘要、查询数上限、批次字节/条目沿用生产常量、TTL 与非滑动语义一致);其余 GatewayCache 方法一律惰性/报错,不建监听器、Redis/SQL、调度或计费写入;ReasoningReplayDiagnosticRejectionCode 直接复用生产 parseOpenAIReasoningRejection,保证诊断不因文案提及而授予恢复;合成租户 APIKey 920000015523/User 920000015522;回放命中/写入计数从 gin context 读取。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S14-svc-openai-reasoning-1-review.json", - "Anchors: attach + synthetic tenant L18-L27, production rejection contract reuse L29-L37, observe counters L39-L55, digest-validated cache keys L104-L109, bounded Put (16 batches, production byte/item limits) L138-L160, CAS delete L161-L176, rejected memory with 64 cap and TTL L177-L219, inert GatewayCache stubs L70-L102.", - "Bridges the production OpenAIReasoningStateStore interface from openai_reasoning_state_cache.go for the diagnostic only; no alternate business rule.", - "Statically read only; tests were not executed and no production behavior was verified." - ] - }, - { - "path": "backend/internal/service/remote_skill_prompt.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "529d0c49ad86fd2904f4674dd9232637e221902c7e024ce09540970de35ed787", - "review_fingerprint": "529d0c49ad86fd2904f4674dd9232637e221902c7e024ce09540970de35ed787", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_prompt_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3b1001a473fbc4e9670aa2996413148f07512c8a870cd9f32afaf21301207507", - "review_fingerprint": "3b1001a473fbc4e9670aa2996413148f07512c8a870cd9f32afaf21301207507", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_publication.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "854a1a88920f66e35184a1a868292dfcab6e682f11f34f136d7402a6d1d75bd9", - "review_fingerprint": "854a1a88920f66e35184a1a868292dfcab6e682f11f34f136d7402a6d1d75bd9", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_publication_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2a79931f071aef70630835f969fe4df2758495428bd1582069436a857a58e851", - "review_fingerprint": "2a79931f071aef70630835f969fe4df2758495428bd1582069436a857a58e851", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "2db691fb39012e8b3ecdf5654b689582e7db038a31ffcc7e65656f346e18e25c", - "review_fingerprint": "2db691fb39012e8b3ecdf5654b689582e7db038a31ffcc7e65656f346e18e25c", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_filesystem.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "2f4ccf17f24210e26034f505567d06bf76eeb0993b06c91de452de717aff7f87", - "review_fingerprint": "2f4ccf17f24210e26034f505567d06bf76eeb0993b06c91de452de717aff7f87", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_filesystem_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9b261c85ac666e3032ebd3c1e7d909fd7da4acd8e6f12582f8c1540c3bf881b1", - "review_fingerprint": "9b261c85ac666e3032ebd3c1e7d909fd7da4acd8e6f12582f8c1540c3bf881b1", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_manifest.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "b19447050dba028c280c138f8e4d837bb37aab1a1a35959f54f0cf566ba3573c", - "review_fingerprint": "b19447050dba028c280c138f8e4d837bb37aab1a1a35959f54f0cf566ba3573c", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_manifest_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f529a5bd9b7c5886d46a7987f8284efbea7641754661efd99da44818b56c2b61", - "review_fingerprint": "f529a5bd9b7c5886d46a7987f8284efbea7641754661efd99da44818b56c2b61", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_source.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "2ebe962c73618ae29487a7b597ad207b990482912c1b19ca73af5a3b63f26a3e", - "review_fingerprint": "2ebe962c73618ae29487a7b597ad207b990482912c1b19ca73af5a3b63f26a3e", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_source_provenance_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8c388218ac464fa886e717213d7dd509178fd2b6fb9ee63e6be9653d3a939447", - "review_fingerprint": "8c388218ac464fa886e717213d7dd509178fd2b6fb9ee63e6be9653d3a939447", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_source_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "e84a2ebe64ec6bcd283a90a04bacf914d93d778861a8b8734772fd3429fe1a7f", - "review_fingerprint": "e84a2ebe64ec6bcd283a90a04bacf914d93d778861a8b8734772fd3429fe1a7f", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "36eed723941c168d35a6f5366b7c19142e311d5ec2e942430bd3db6a3c032496", - "review_fingerprint": "36eed723941c168d35a6f5366b7c19142e311d5ec2e942430bd3db6a3c032496", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_registry_validation.go", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "929ea25ccd6bf6e63c7e97caaab4166d4595cfda3fc207e4764194a748e2341c", - "review_fingerprint": "929ea25ccd6bf6e63c7e97caaab4166d4595cfda3fc207e4764194a748e2341c", - "review_status": "pending" - }, - { - "path": "backend/internal/service/remote_skill_seed_fixture_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3147b7527f320a71f5075e4270c774a88ae0ec10d94aafb750c180f4d6d7700a", - "review_fingerprint": "3147b7527f320a71f5075e4270c774a88ae0ec10d94aafb750c180f4d6d7700a", - "review_status": "pending" - }, - { - "path": "backend/internal/service/responses_chat_protocol_callers_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "bfe0fa29bc6a76c4dcb19c4ca221b9d8ea2fd794424e91fe7b6d451f13601a7c", - "review_fingerprint": "bfe0fa29bc6a76c4dcb19c4ca221b9d8ea2fd794424e91fe7b6d451f13601a7c", - "review_status": "pending" - }, - { - "path": "backend/internal/service/scheduled_test_port.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "89428d9a874f47be7553a9b4d91ac35358e71742fe842740cc59529f3f33d90b", - "review_fingerprint": "89428d9a874f47be7553a9b4d91ac35358e71742fe842740cc59529f3f33d90b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "定时测试(账号连通性巡检)领域模型与仓储端口定义:ScheduledTestPlan/ScheduledTestResult 结构 + Plan/Result Repository 接口。下游唯一改动:ScheduledTestResult 新增 RequestedReasoningEffort/EffectiveReasoningEffort 两个 omitempty 观测字段。该功能是 core 管理端(AccountTestService/ScheduledTestService + admin handler)特性,无插件持有;字段被 account_test_service.go 填充、admin/account_job_execution.go 消费。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: +RequestedReasoningEffort/+EffectiveReasoningEffort on ScheduledTestResult (struct reordered, JSON tags omitempty).", - "Consumers: account_test_service.go:3310-3311/3461 set them; handler/admin/account_job_execution.go:84 reads EffectiveReasoningEffort into metadata.", - "No plugin references ScheduledTest (rg plugins empty) -> core admin feature, not a plugin domain.", - "Port/interface definitions only; no execution here." - ] - }, - { - "path": "backend/internal/service/scheduler_snapshot_bulk_event_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6da3dbb7f6720b3f208a6fcacb29ac1b928fd26c2fc1bd376f894b09ae5d7ccb", - "review_fingerprint": "6da3dbb7f6720b3f208a6fcacb29ac1b928fd26c2fc1bd376f894b09ae5d7ccb", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "调度快照批量账号事件(handleBulkAccountEvent)的单测,250 行全读:验证按平台收敛重建、未分组桶、simple 模式归零、缺失账号/未知平台回退全平台、Antigravity 兼容平台保守扩散。下游相对上游只新增两处:给账号仓库桩补 GetByID(L30-L38),以及 TestSchedulerRefreshAccountAndGroupsRebuildsOldAndNewBuckets(L127-L140)证明下游新增的同步入口 RefreshAccountAndGroups(12, [81,82]) 复用 outbox 账号事件路径、同时重建旧组 81 和新组 82 的桶并回写账号缓存。该入口由宿主侧 Cindy 账号任务 runner(repository/account_job_cindy_mutation.go:135)在合并新旧组后调用,属核心快照机制的同步变体而非插件业务,故归 core-mechanism。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S16-svc-account-scheduler-2-review.json", - "Diff vs aea725f adds only bulkEventAccountRepo.GetByID stub (L30-L38) and TestSchedulerRefreshAccountAndGroupsRebuildsOldAndNewBuckets (L127-L140), asserting buckets for group 81 (old) and 82 (new) on PlatformOpenAI plus SetAccount([12]).", - "Call chain: RefreshAccountAndGroups (scheduler_snapshot_service.go:329) -> handleAccountEvent -> rebuildByAccount; sole production caller accountJobCindyMutationRunner.Run (backend/internal/repository/account_job_cindy_mutation.go:135) passes mergeCindyAccountMutationGroupIDs(previous, new) per the documented old+new contract, alongside a durable SchedulerOutboxEventAccountChanged enqueued in the same transaction — same executor path, no duplicate.", - "No production behavior edit and no test execution for this test-only file." - ] - }, - { - "path": "backend/internal/service/scheduler_snapshot_group_lifecycle_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "22b47cdc671d1ef9f48e3349bf81bc41a6dab9627bd767774137309b5d8ac63d", - "review_fingerprint": "22b47cdc671d1ef9f48e3349bf81bc41a6dab9627bd767774137309b5d8ac63d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "分组生命周期(租约内 Retire/Reopen、epoch 防 ABA、失败不标记 seen、独立释放上下文、group0/simple 模式 no-op)的单测,828 行全读。下游相对上游新增 TestSchedulerCanonicalBucketsIncludeCindyAndMiniMax(L342-L365,钉死 canonical 桶数 24、账号查询数 13,且 Cindy/MiniMax 的 single+forced 桶必须在列),并在 inactive 退休用例(L420-L424)与 active 重建用例(L488-L489)中补 Cindy/MiniMax 桶与每平台查询次数断言。这是对下游把 PlatformCindy 加入核心调度平台注册表(scheduler_snapshot_service.go:840)后生命周期路径的守护:禁用分组时 Cindy 桶也被退休、启用时也被重建,防止平台枚举回退导致 Cindy 快照残留或漏建。被测主体全部是宿主调度机制,Cindy 业务规则不在此文件。静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S16-svc-account-scheduler-2-review.json", - "Diff vs aea725f: +TestSchedulerCanonicalBucketsIncludeCindyAndMiniMax L342-L365 (bucketCount=24, queryCount=13 for standard mode); inactive/missing retire test asserts Cindy+MiniMax single/forced buckets retired L420-L424; active rebuild asserts platformCallCount(PlatformCindy)==1 and (PlatformMiniMax)==1 at L488-L489.", - "Subjects traced: schedulerCanonicalBuckets/schedulerCanonicalBucketCount/schedulerSnapshotPlatforms (scheduler_snapshot_service.go:840-877) — downstream added only PlatformCindy to the [11]string registry; MiniMax was already upstream; lease/retire/reopen semantics under test (prepareGroupLifecycle, scheduler_snapshot_service.go:728+) are unchanged host mechanism.", - "No production behavior edit and no test execution; concurrency-oriented assertions (fencing, seen-map) were read statically only." - ] - }, - { - "path": "backend/internal/service/scheduler_snapshot_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "fd559bdfc1650677d62831772d2d9f17eae430ae198f0ff62cbd5364410332c9", - "review_fingerprint": "fd559bdfc1650677d62831772d2d9f17eae430ae198f0ff62cbd5364410332c9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "调度快照宿主服务(1746 行全读):outbox 消费与水位推进、桶写令牌/围栏、分组生命周期租约、全量重建合并、DB 回退限流。下游相对上游 aea725f 改四处:新增同步入口 RefreshAccountAndGroups(L325-L340),直接复用 outbox 的 handleAccountEvent 路径(同一执行器,无重复实现),供 Cindy 账号任务在管理端变更返回前立即清理旧组桶;把 PlatformCindy 加入 schedulerSnapshotPlatforms([10]→[11],L840)与 handleBulkAccountEvent 的已知平台 switch(L625),使 Cindy 账号的批量事件按平台收敛重建而不是回退全平台;schedulerCanonicalBuckets 的容量改用 schedulerCanonicalBucketCount()(构造性正确);GetGroupByIDLite 注释由中文利润门说明改为简洁英文(L309,纯注释)。Cindy 的业务规则(凭证轮换、健康态清理)留在 repository 的 job runner 与 cindy-provider 域,这里只有平台枚举与通用重建机制,故归 core-mechanism。静态阅读,未执行测试或构建。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S16-svc-account-scheduler-2-review.json", - "Diff vs aea725f: +RefreshAccountAndGroups L325-L340 delegating to handleAccountEvent with a fresh seen map; PlatformCindy added to the known-platform switch in handleBulkAccountEvent (L625) and to schedulerSnapshotPlatforms [11]string (L840-L842); schedulerCanonicalBuckets capacity now schedulerCanonicalBucketCount() (L863-L865); GetGroupByIDLite comment rewrite only (L309).", - "Call chain and ownership: sole caller of RefreshAccountAndGroups is backend/internal/repository/account_job_cindy_mutation.go:135 (2s bounded context.WithoutCancel, after committing a SchedulerOutboxEventAccountChanged in the same transaction, so durability stays with the outbox and the sync call is a best-effort immediacy optimization — failure only logs); unknown platforms in handleBulkAccountEvent still fall back to rebuildByGroupIDs over all platforms, so adding Cindy narrows rebuild scope without dropping coverage.", - "Checked for defect classes while reading: no unbounded map (seen maps are per-poll, query cache entries released per bucket via schedulerAccountQueryCache.release), lease always released via defer with errors.Join and an independent 2s release context, watermark only advances after every event in the batch succeeded. No defect recorded.", - "No production behavior edit, no test/build execution for this file." - ] - }, - { - "path": "backend/internal/service/setting_codex_ticket_test.go", - "candidate_owner": "codex-runtime", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4a705096d456f93919337743295f17e78bae331bf1cd452d3cec31c80a0810ec", - "review_fingerprint": "4a705096d456f93919337743295f17e78bae331bf1cd452d3cec31c80a0810ec", - "review_status": "pending" - }, - { - "path": "backend/internal/service/setting_gateway_runtime.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "d240884d8aeb5f9cddb84051815181728bc7d49e93435d46cffafcb7b5dbeecf", - "review_fingerprint": "d240884d8aeb5f9cddb84051815181728bc7d49e93435d46cffafcb7b5dbeecf", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "SettingService 面向网关热路径的进程内缓存读取器(Claude Code 版本上下限、backend mode、转发行为、Antigravity/Codex UA 与客户端版本、codex_cli_only 加固策略及其三项迁移、cyber 会话屏蔽、quota auto-pause stale-while-revalidate)。下游新增 OpenAIRefusalRecoveryRuntime:60s TTL + singleflight + 互斥 CAS 提交(commitOpenAIRefusalRecoveryRuntime 让迟到的 DB 结果不覆盖 refreshCachedSettings 刚写入的新值)+ 出错 5s 保留旧快照;仅 Enabled&&Rewrite 时构造 matcher,失败则关闭 Rewrite;另为 getGatewayForwardingSettingsCached 增加 nil repo 安全默认。refusal 业务规则本身在 openai_refusal_recovery.go/网关(其他 slice),这里只是设置缓存机制。见 findings:两个 API-key 兼容开关被缓存但无消费者。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (1189 lines, 3 chunks). git diff aea725f: +OpenAIRefusalRecoveryRuntime block (~L159-L288: struct, cached wrapper, TTL consts, CyberFailoverEnabled/RewriteEnabled, commitOpenAIRefusalRecoveryRuntime, cachedOpenAIRefusalRecoveryErrorRuntime, GetOpenAIRefusalRecoveryRuntime, buildOpenAIRefusalRecoveryRuntime) and nil-guard defaults in getGatewayForwardingSettingsCached (~L872-L880).", - "Consumers: openai_refusal_recovery.go:256 (*OpenAIGatewayService).openAIRefusalRecoveryRuntime -> settingService.GetOpenAIRefusalRecoveryRuntime; RewriteEnabled()/Matcher used in openai_gateway_passthrough.go:2217/2870/2964 and openai_gateway_response_handling.go:204; CyberFailoverEnabled() in openai_cindy_http_wsv2.go:204/288.", - "Concurrency: singleflight key openai_refusal_recovery; CAS compares observed pointer under openAIRefusalRecoveryCacheMu; refreshCachedSettings (setting_update.go) Forgets the key and stores under the same mutex; proven by setting_gateway_runtime_refusal_test.go.", - "FINDING (low): runtime fields APIKeyAlphaSearchResponsesBridge/APIKeyPromptCacheKeyNormalization (L162-L163, loaded L236-L237/L266-L267) have no reader anywhere in backend/internal non-test code; dead settings plumbing." - ] - }, - { - "path": "backend/internal/service/setting_gateway_runtime_refusal_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "88b4a1ed67cc1a89aa6c746fa3b1f7fbc908645d3490e6b8c2350571f212cfa3", - "review_fingerprint": "88b4a1ed67cc1a89aa6c746fa3b1f7fbc908645d3490e6b8c2350571f212cfa3", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "新增文件,SettingService 的 OpenAI refusal-recovery 运行时缓存单测。断言:无 settingRepo 时网关转发设置取安全默认;加载 API-key 兼容开关(alpha-search bridge / prompt-cache-key 归一化);刷新失败保留上次快照(仍可匹配);refusal 总开关关时仍加载 cyber failover 且无 matcher;初次刷新失败默认全禁用;以及并发下 in-flight DB 读不会用旧值覆盖显式 refreshCachedSettings 写入的新值(commit CAS)。被测主体是 core 网关设置运行时缓存(refusal 特性执行在 codex-runtime 网关侧)。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review; new file (ls-tree aea725f empty).", - "TestOpenAIRefusalRuntimeRefreshDoesNotOverwriteNewSettings blocks GetMultiple, calls refreshCachedSettings mid-flight, and asserts the newer settings win — proves commitOpenAIRefusalRecoveryRuntime CAS.", - "TestOpenAIRefusalRuntimeKeepsLastKnownSnapshotOnRefreshError proves 5s error-TTL stale fallback still matches via Matcher.MatchLeadingParagraphs; getMultipleCalls==2, getValueCalls==0.", - "TestGatewayForwardingSettingsWithoutRepositoryUseSafeDefaults covers the nil-repo default guard added in setting_gateway_runtime.go; test read statically, not executed." - ] - }, - { - "path": "backend/internal/service/setting_parse.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "ca22797e8ee4c6d2d2196e0b14341811edefc74add10abc167eb88895ef8acc1", - "review_fingerprint": "ca22797e8ee4c6d2d2196e0b14341811edefc74add10abc167eb88895ef8acc1", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "SettingService 的默认值初始化(InitializeDefaultSettings 一次性种子)与 parseSettings(把 settings 表 KV 解析成 SystemSettings:注册/登录协议/SMTP/验证码/LinuxDo/DingTalk/OIDC/GitHub/Google/WeChat 回退 config、Ops、渠道监控、Grok、模型广场、affiliate、codex_cli_only、高级调度权重、平台配额、停调阈值等)以及表格/订阅/授权来源默认发放解析。下游改动仅两处:种子表新增 7 个 OpenAI refusal/cyber/API-key 开关键(默认 false、关键词取 defaultOpenAIRefusalKeywordsJSON),parseSettings 解析同 7 键(关键词经 parseOpenAIRefusalKeywordsSetting)。generic 宿主设置机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (1351 lines, 3 chunks). git diff aea725f: +7 default keys in InitializeDefaultSettings (L222-L230) and +7 parse lines in parseSettings (L855-L861).", - "parseOpenAIRefusalKeywordsSetting / defaultOpenAIRefusalKeywordsJSON are defined in openai_refusal_recovery.go (other slice); setting keys in domain_constants.go:246-252.", - "Secrets are returned raw only for admin test-connection (SMTPPassword/Turnstile/captcha secrets) as upstream already did; downstream delta adds no secret handling.", - "Two of the seven keys (alpha-search bridge, prompt-cache-key normalization) are parsed here but have no request-path consumer — see the setting_gateway_runtime.go finding." - ] - }, - { - "path": "backend/internal/service/setting_public.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "f3775f6531c60f97dafa4840b9eae0f6c44af553ddd201c73dd3b6ac525bffc5", - "review_fingerprint": "f3775f6531c60f97dafa4840b9eae0f6c44af553ddd201c73dd3b6ac525bffc5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "SettingService 公开(无需登录)设置:登录协议文档归一化/修订哈希、GetPublicSettings 的键列表与回退 config、渠道监控/可用渠道/模型广场运行时读取(fail-open/fail-closed 语义各自注释)、HTML 注入载荷 PublicSettingsInjectionPayload(与 dto.PublicSettings 键同步的不变量)、用户可见菜单过滤、CSP frame-src origin 提取。下游改动:PublicSettings/注入载荷新增 ImageStudioEnabled,取值 CindyImageStudioFeatureEnabled()(进程级 image-tools rollout 标志,非 DB 设置),并把 ChannelMonitorShowQuota 的注释与字段位置对齐。宿主公开设置机制,ImageStudioEnabled 是向 image-tools 领域的一条 feature-flag 透出。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (856 lines, 2 chunks). git diff aea725f: +ImageStudioEnabled in GetPublicSettings (L368), in PublicSettingsInjectionPayload (~L640) and in GetPublicSettingsForInjection mapping (~L725); ChannelMonitorShowQuota field reordered under its comment.", - "CindyImageStudioFeatureEnabled (cindy_feature_flags.go:91) is the one-release alias of ImageStudioFeatureEnabled reading currentImageToolsConfig().StudioEnabled; consumed by frontend/src/stores/app.ts (image_studio_enabled) and dto/settings.go:459.", - "No secrets exposed: public key list excludes secret keys except WeChat app-secret keys already fetched upstream for capability derivation (unchanged by delta).", - "Static review only; the injection-vs-DTO key parity test (setting_service_injection_test.go) was not executed." - ] - }, - { - "path": "backend/internal/service/setting_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "10d1b5fff4e0e050713e6a6714824f49dfe092a4f835773ba9a8523b3f6e37dd", - "review_fingerprint": "10d1b5fff4e0e050713e6a6714824f49dfe092a4f835773ba9a8523b3f6e37dd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "SettingService 核心定义:Grok base URL 模式解析、SettingRepository 接口、SettingService 结构体(各热路径缓存 atomic.Value+singleflight)、平台配额/授权来源默认发放类型与键集、LoadForwardedClientIPSettings 迁移(v2 模式位与可信代理兼容)、GetAllSettings、更新回调与渠道监控监听器。下游改动仅:结构体新增 openAIRefusalRecoveryCache/SF/CacheMu 三个字段(供 setting_gateway_runtime.go 的 refusal 运行时缓存使用)与 sync import 位置调整。generic 宿主设置机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (445 lines). git diff aea725f: +openAIRefusalRecoveryCache atomic.Value, +openAIRefusalRecoverySF singleflight.Group, +openAIRefusalRecoveryCacheMu sync.Mutex (L138-L140); import order of sync.", - "Fields are used by GetOpenAIRefusalRecoveryRuntime/commitOpenAIRefusalRecoveryRuntime (setting_gateway_runtime.go) and refreshCachedSettings (setting_update.go) — per-instance cache, test isolation preserved.", - "LoadForwardedClientIPSettings and listener code are upstream-identical in this delta; no permission or secret handling changed.", - "Static review only." - ] - }, - { - "path": "backend/internal/service/setting_service_platform_quota_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1807197119d5064571b5c3d03c7c37a9f3f7759b66c8d2a32f968fbaac452d7a", - "review_fingerprint": "1807197119d5064571b5c3d03c7c37a9f3f7759b66c8d2a32f968fbaac452d7a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "平台配额设置单测(//go:build unit):mergePlatformQuotaDefaults 补丁语义(0=显式禁用、nil=沿用)、GetDefaultPlatformQuotas 对 AllowedQuotaPlatforms 的补齐契约、授权来源配额的 override 语义(未配置平台不出现)、buildSystemSettingsUpdates→GetDefaultPlatformQuotas 写读往返、空 map 整体清空、nil 保留既有、负数拒绝(INVALID_DEFAULT_PLATFORM_QUOTA)。下游改动:在补齐契约与往返用例中加入 Cindy(daily 7.5)与 MiniMax(monthly 42)并断言 len==len(AllowedQuotaPlatforms)、MiniMax 不继承 Cindy 的配额——锁住下游新增平台不串值。被测主体 core 配额设置机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (353 lines). git diff aea725f: seed adds \"cindy\":{\"daily\":7.5}; +require.Len(got,len(AllowedQuotaPlatforms)), +Cindy/MiniMax assertions in TestGetDefaultPlatformQuotas_ReturnsAllowedPlatforms and TestSystemPlatformQuotas_WriteReadRoundTrip.", - "Proves platform-fill contract extends to downstream-added platforms (PlatformCindy, PlatformMiniMax) without cross-inheritance; validateDefaultPlatformQuotaMap rejects negatives.", - "Uses newMockSettingRepo + NewSettingService with empty config; exercises UpdateSettings/UpdateSettingsWithAuthSourceDefaults real write->read path.", - "Test read statically, not executed." - ] - }, - { - "path": "backend/internal/service/setting_update.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "520c7682e88597193054b1e991f17c5d41569f2fe518242ae671a2135cc9a013", - "review_fingerprint": "520c7682e88597193054b1e991f17c5d41569f2fe518242ae671a2135cc9a013", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "SettingService 写路径:UpdateSettings(Omitting) 部分载荷语义、buildSystemSettingsUpdates 的归一化/校验与 KV 序列化(密钥非空才写、平台配额与停调阈值校验、整体替换语义)、授权来源默认发放写入、refreshCachedSettings 刷新全部进程内缓存并通知监听器。下游改动:校验 NormalizeOpenAIRefusalKeywords + ValidateOpenAIRefusalRecoverySettings(INVALID_OPENAI_REFUSAL_RECOVERY);写入 7 个 refusal/cyber/API-key 键(关键词 JSON);refreshCachedSettings 在互斥锁内 Forget singleflight 并直接重建 OpenAIRefusalRecoveryRuntime 缓存。generic 宿主设置机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (880 lines, 2 chunks). git diff aea725f: validation block (L118-L125), 7 update keys (L463-L473), refusal cache rebuild in refreshCachedSettings (L713-L731).", - "NormalizeOpenAIRefusalKeywords / ValidateOpenAIRefusalRecoverySettings live in openai_refusal_recovery.go (other slice); marshal failure of keywords returns an error rather than writing partial state.", - "Cache rebuild holds openAIRefusalRecoveryCacheMu while Forget+Store, matching the CAS in setting_gateway_runtime.go; partial payloads (OmittedSettingKeys) rebuild caches from stored settings instead of the request struct.", - "Two of the written keys have no request-path consumer — see the setting_gateway_runtime.go finding; static review only." - ] - }, - { - "path": "backend/internal/service/settings_view.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0f9d74a90142e76b3418da5519ed461cc16f0e8330635ea8601fe1a6182c04ae", - "review_fingerprint": "0f9d74a90142e76b3418da5519ed461cc16f0e8330635ea8601fe1a6182c04ae", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "设置领域视图类型:SystemSettings(管理端全量)、PublicSettings、LoginAgreementDocument、WeChatConnectOAuthConfig 的 mode/scope/app 选择方法、流超时/整流器/Beta 策略/529 与 429 冷却/OpenAI images OAuth 冷却/API-key 健康熔断/OpenAI fast 策略等设置结构与默认值。下游改动仅:SystemSettings 新增 7 个 OpenAI refusal/cyber/API-key 字段(含 OpenAIRefusalKeywords []string),PublicSettings 新增 ImageStudioEnabled。纯类型定义,generic 宿主。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (734 lines, 2 chunks). git diff aea725f: +7 SystemSettings fields (L173-L179) and +PublicSettings.ImageStudioEnabled (L409); gofmt realignment of neighbouring fields.", - "Fields are populated by setting_parse.go, written by setting_update.go, exposed via setting_public.go / handler dto; no logic in this file.", - "DefaultBetaPolicySettings/OpenAI fast policy constants are upstream-identical in this delta.", - "Static review only." - ] - }, - { - "path": "backend/internal/service/temp_unsched.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "5538fa85f98dd7acc3ced7e4087fd5301bacf5543bfd3bd37a65eec22cea9b8b", - "review_fingerprint": "5538fa85f98dd7acc3ced7e4087fd5301bacf5543bfd3bd37a65eec22cea9b8b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "账号临时不可调度(temp-unsched)状态的缓存/仓储接口契约。下游新增两个可选接口:TempUnschedGuardedClearRepository.ClearTempUnschedulableIfMatch(按 DB 原值 reason+until 做 compare-and-clear)与 TempUnschedGuardedCache(按缓存快照 CAS 删除),用于避免清除一个同秒过期但已被重建的暂停——一个陈旧态竞态防护机制。仅接口声明,实现在 repository/cache(其他 slice)。属调度机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: +TempUnschedGuardedClearRepository and +TempUnschedGuardedCache interfaces (2 methods each).", - "Doc comments require DB-sourced reason/until (NULL reason as \"\", until as the stored timestamptz, not a locally recomputed deadline) to make the CAS safe.", - "Declarations only; scheduling-pause state management is core-quota-and-protocol.", - "No business execution here; no defect." - ] - }, - { - "path": "backend/internal/service/testdata/account_available_models_contract.json", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9a4c3080ca8d0c9e234738171f087a1b30408d2e2be029fafd60a8e48b4ac7d9", - "review_fingerprint": "9a4c3080ca8d0c9e234738171f087a1b30408d2e2be029fafd60a8e48b4ac7d9", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "OpenAI 账号可用模型展示投影的契约夹具:`upstream` 为 /v1/models 原始目录(含只有 id、以及 null/空串/纯空白 display_name 与 type 的边界项),`expected` 为投影后应得的 picker 模型(补 object=model、created=0、owned_by=openai、type=model,display_name 在 null/空/空白时回落为 id,已有元数据如 context_window/max_*_tokens 原样保留)。被 service/account_available_models_test.go 消费,验证 AccountTestService.FetchOpenAIAccountModels 只补展示字段、不改动共享发现缓存与账号凭据、上游仅调用一次。属宿主对 OpenAI 网关模型目录的发现/投影,非插件业务;上游无此文件(整文件为下游新增)。仅静态阅读该 JSON 数据,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S26-svc-rest-1-review.json", - "New downstream file (git ls-tree aea725f -- empty); whole 1541-byte JSON is the delta: 6 upstream inputs -> 6 normalized expected models, defaults owned_by=openai/object=model/type=model, display_name falls back to id for null/\"\"/\" \\t\\n\".", - "Consumer: backend/internal/service/account_available_models_test.go TestAccountAvailableModelsProjectsDiscoveryWithoutChangingCache asserts models==fixture.Expected and non-empty trimmed DisplayName/Type; subject AccountTestService.FetchOpenAIAccountModels (account_test_service.go:193) unmarshals a fresh copy of the cached body and fills display defaults via openaiCodexDisplayName (openai_codex_models_service.go:710) without mutating gateway cache/ETag.", - "Not a plugin executor and no second executor found; not claiming the test passes or any runtime/gateway behavior was exercised — this fixture was only read statically." - ] - }, - { - "path": "backend/internal/service/testdata/cindy_free_catalog_2026-08-29.json", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "863a6d015590106bdd693e7327f5a105d3feac84d075af28c2736cd0db6f9ed8", - "review_fingerprint": "863a6d015590106bdd693e7327f5a105d3feac84d075af28c2736cd0db6f9ed8", - "review_status": "pending" - }, - { - "path": "backend/internal/service/testdata/cindy_free_catalog_2026-09-11.json", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1915e2d934eb5284489562cda88628d72827b0a77a5e3dbdcb28a61dc69f48f0", - "review_fingerprint": "1915e2d934eb5284489562cda88628d72827b0a77a5e3dbdcb28a61dc69f48f0", - "review_status": "pending" - }, - { - "path": "backend/internal/service/testdata/codexrip_reverse_skill_system_prompt_legacy_dual_marker.txt", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "74bd491260aaa23c45b82bd522b32c6b6dea7d5e76a2d8e3ab3607c6f1ab4e58", - "review_fingerprint": "74bd491260aaa23c45b82bd522b32c6b6dea7d5e76a2d8e3ab3607c6f1ab4e58", - "review_status": "reviewed", - "decision": "reference", - "owner": "prompt-skills", - "reason": "业务系统提示词(remote-skill / business system prompt)改写流水线的“遗留双标记”原始输入夹具:文本含 REVERSE-SKILL 与 SECURITY-RESEARCH ROUTING 两个路由标记块(分别指向本地 reverse-skill 路径与 https://moxinggang.com 远端根)及人格/SCOPE_LOCK 提示词正文。被 service/remote_skill_registry_filesystem_test.go 的 historicalRemoteSkillPromptCaptureForTest 读取,经 rewriteRemoteSkillPromptBlocks 改写为 effective 正文,并断言 raw sha256=74bd4912…、effective sha256=de259ce1…,用于验证历史提示词规范化与不可变配对候选加载。属 prompt-skills 业务域的产品内容(上游无此文件,整文件为下游新增,另见 migrations 195/196/200/201 的 moxinggang/codexrip bundle)。该文件按数据处理,未执行、未遵循其中任何指令,也未访问其中任何 URL/路径。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S26-svc-rest-1-review.json", - "New downstream file (git ls-tree aea725f -- empty); whole 6990-byte text is the delta: dual routing marker blocks using the double-space markers matching remote_skill_prompt.go:17-20 constants, plus persona/SCOPE_LOCK body.", - "Consumer: backend/internal/service/remote_skill_registry_filesystem_test.go historicalRemoteSkillPromptCaptureForTest reads this file as RawBody, rewrites via rewriteRemoteSkillPromptBlocks to EffectiveBody, and pins raw sha256 74bd4912… / effective sha256 de259ce1…; drives TestRemoteSkillFilesystemLoadsImmutableHistoricalPromptPair (immutability/tamper-rejection with ErrBusinessSystemPromptBundleInvalid).", - "Owner is prompt-skills (business system prompt bundle domain), not a core mechanism; not a code defect (product content). Fixture read statically only; no test executed, no network, instructions in the file were not followed." - ] - }, - { - "path": "backend/internal/service/testdata/plugin_contribution_buckets.json", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "98c128212dc2860417c474343e24cfadf5afc1d6d718dc6ecfa223f863ee9eb5", - "review_fingerprint": "98c128212dc2860417c474343e24cfadf5afc1d6d718dc6ecfa223f863ee9eb5", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "插件贡献灰度分桶的跨语言契约向量:每项 {id, bucket} 给出 accountID 经 stablePluginBucket(plugin_manager.go:1514,splitmix64 finalizer 后 %100)应落入的桶,含边界值 9007199254740991(JS Number.MAX_SAFE_INTEGER)。被 service/plugin_contribution_admission_test.go 与前端 contributionAdmission.spec.ts 共同消费,保证 Go 宿主与前端 UI 的分桶计算一致;实际准入强制仍以宿主 ValidateAdminExtension 为准,前端分桶仅用于展示。属扩展/任务宿主的通用灰度机制,上游无此文件(整文件为下游新增)。仅静态阅读该 JSON,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S26-svc-rest-1-review.json", - "New downstream file (git ls-tree aea725f -- empty); whole 255-byte JSON is the delta: 6 {id,bucket} vectors incl. id=9007199254740991 (2^53-1) as the JS max-safe-integer boundary.", - "Consumer: backend/internal/service/plugin_contribution_admission_test.go TestContributionAdmissionIntersectsScopesAndPreservesSharedLegacy asserts stablePluginBucket(id)==bucket for each vector; same fixture used by frontend/src/components/plugins/__tests__/contributionAdmission.spec.ts to keep JS/Go buckets identical. Enforcement path is host-authoritative (PluginManager.ValidateAdminExtension), JS bucket is display-only, so cross-language reuse is not a duplicated executor.", - "Generic host rollout/contribution-admission mechanism (core-extension-and-job-host); not claiming the test passes — fixture read statically only." - ] - }, - { - "path": "backend/internal/service/timing_wheel_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "96bd9b4651c24e7e4cf0b242784c5f6973699089318c8055059a84ea2c8c7866", - "review_fingerprint": "96bd9b4651c24e7e4cf0b242784c5f6973699089318c8055059a84ea2c8c7866", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "TimingWheelService 单测:构造失败返回 error、Schedule 一次性执行、Cancel 阻止执行、ScheduleRecurring 多次执行、Stop 后调用走 error 日志不 panic、Stop 幂等。下游改动仅在 TestNewTimingWheelService_Success 的 nil 守卫后加 return(无行为变化)。被测主体是 core 通用延时调度原语。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: single '+return' after t.Fatalf svc==nil guard (L33 area).", - "Covers Schedule once-only, Cancel prevents run, recurring executes >=2, Stop idempotent, Schedule/ScheduleRecurring after Stop log-not-panic via newTimingWheel override.", - "Subject: core generic timing-wheel primitive (go-zero collection).", - "Delta is lint hardening only; test read statically, not executed." - ] - }, - { - "path": "backend/internal/service/token_refresh_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "4173b963dfce00eda2483a820c02d9d6fc23a8f661e0e0fd4cb128eafa3f918f", - "review_fingerprint": "4173b963dfce00eda2483a820c02d9d6fc23a8f661e0e0fd4cb128eafa3f918f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "后台 OAuth token 刷新服务(游标分页候选、按平台限流/并发/熔断、统一 refreshAPI 分布式锁路径、Grok 条件 CAS 变更、刷新后隐私设置与调度缓存同步)。下游相对上游 aea725f +73/-14,全部是核心行为的正确性修复:postRefreshActions 把无条件 ClearTempUnschedulable + 无条件 Redis 删除改为原值受限 CAS——先取 Redis 快照,DB 按加载时的 reason+until 做 ClearTempUnschedulableIfMatch,命中才通知运行时解封并按原值删 Redis(DeleteTempUnschedIfMatch);CAS 未命中或仓库不支持受限契约时跳过调度缓存发布,避免把旧 pause 写回(L1182-L1256 与 postRefreshStateSyncWithOptions 的 syncScheduler 参数);notifyAccountSchedulingBlocked 对带 until 的停调改走 notifyPersistedAccountSchedulingCooldown(L191-L194)。消除并发改写停调状态时的丢失更新/误解封竞态。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "1587 行全读;diff 锚点:L191-L194 persisted cooldown 分支、L1182-L1256 guarded CAS 清除(cachedSnapshot 先于 DB CAS 采样、applied 才清内存 TempUnschedulable 字段)、L1271-L1277 postRefreshStateSyncWithOptions 新增 syncScheduler 开关、L1288 条件化 schedulerCache.SetAccount。", - "调用链:ClearTempUnschedulableIfMatch 契约定义于 service/temp_unsched.go L41-L46、实现于 repository/account_repo.go L2637;DeleteTempUnschedIfMatch 于 repository/temp_unsched_cache.go L129;notifyPersistedAccountSchedulingCooldown 于 service/ratelimit_service.go L58;同一受限清除模式也用于 cn_provider_balance_check_service.go L254——非本域第二执行体,是同一契约的另一调用方。", - "发现一处上游携带的低危死代码(见 findings,L681-L688 重复 isTripped 检查),不影响行为;未对其做任何修改。", - "No production behavior edit or test execution for this file." - ] - }, - { - "path": "backend/internal/service/token_refresh_service_candidates_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5a8867c6b873aa1d6a5bda92a8d95df959b7b1388e28bf8912565c7707b74b17", - "review_fingerprint": "5a8867c6b873aa1d6a5bda92a8d95df959b7b1388e28bf8912565c7707b74b17", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "token 刷新候选分页路径的单元测试:证明 processRefresh 走 ListOAuthRefreshCandidatePage 而非全量 ListActive(listActiveCalls 必须为 0)、仅前缀为 token refresh retry exhausted: 的停调进入重试冷却排除、暂停调度(schedulable=false)但 active 的账号仍必须刷新以防 token 过期(L203-L207)、刷新失败绝不触发 privacy 工厂、不可重试错误 SetError 而重试耗尽走 SetTempUnschedulable(L210-L254)。下游相对上游仅 +7 行:给 mock 仓库补 ClearTempUnschedulableIfMatch 存根(L101-L106),使既有断言 clearTempCalls==1 现在证明的是受限 CAS 清除路径被使用(服务已不再无条件清除)。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "254 行全读;锚点:tokenRefreshCandidateRepo.ListOAuthRefreshCandidatePage 的过滤逻辑复刻(L35-L70)、TestTokenRefreshService_ProcessRefreshUsesOAuthRefreshCandidates 的 ElementsMatch {1,6,7}(L206)。", - "git diff aea725f 仅新增 ClearTempUnschedulableIfMatch 存根方法,返回 (true, nil) 并复用 clearTempCalls 计数——与 token_refresh_service.go 下游 guarded CAS 修复配套。", - "No test execution; statically read only." - ] - }, - { - "path": "backend/internal/service/token_refresh_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a53356937c5fd388a34044ffa18c4a5df741db1b058c8ff1ed66a166442549a1", - "review_fingerprint": "a53356937c5fd388a34044ffa18c4a5df741db1b058c8ff1ed66a166442549a1", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "token 刷新服务主测试(1683 行,unit tag):覆盖缓存失效与调度缓存同步、Antigravity 强制刷新标记、Path A(refreshAPI 分布式锁)成功/锁占用/已刷新/持久化失败、Grok 条件 CAS(并发修复获胜、契约缺失或 CAS 报错按 provider 周期遏制)、跨 attempt 截止时间的持久化成功不重试不计熔断、isNonRetryableRefreshError 表。下游相对上游 +61/-8,专证 guarded CAS 清除修复:mock 增加 ClearTempUnschedulableIfMatch/GetTempUnschedSnapshot/DeleteTempUnschedIfMatch 存根,ClearsTempUnschedulable 用例断言 CAS 收到加载时的 DB 快照(reason+until)、Redis 删除按整段原值受限,并新增子测试证明 CAS 未命中时不动 Redis、不通知解封、不把旧 pause 写回调度缓存(L877-L909)。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "1683 行全读;diff 锚点:tokenRefreshAccountRepo 新增 clearIfMatchMiss/lastClearIfMatchReason/lastClearIfMatchUntil 字段(L47-L50) 与存根(L114-L120)、tempUnschedCacheStub 新增快照字段与 GetTempUnschedSnapshot/DeleteTempUnschedIfMatch(L362-L397)、TestTokenRefreshService_RefreshWithRetry_ClearsTempUnschedulable 扩展断言与 snapshot mismatch skips redis delete 子测试(L850-L909)。", - "上游已有的 Grok CAS/PathA 用例未被下游改动(不在 diff 内),此记录只把下游新增断言计为修复证据;被测主体为 token_refresh_service.go 的下游 delta。", - "No test execution; statically read only." - ] - }, - { - "path": "backend/internal/service/update_service.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "92fd125e3642835e5707c82f887dc1214f994719def20548fcc9175b7a7662da", - "review_fingerprint": "92fd125e3642835e5707c82f887dc1214f994719def20548fcc9175b7a7662da", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "自更新服务(GitHub release 检查/缓存、仅 github.com/objects.githubusercontent.com HTTPS 下载、checksums 校验、tar 防路径穿越与解压炸弹、原子替换与备份回滚、最多 3 个更旧版本的回滚列表)。下游新增 updateStrategyForVersion:版本带 codexrip.N / refusal-recovery.N 后缀(N>0)判为 downstream,基础版取前缀;此时 HasUpdate 永远为 false(只暴露 UpstreamUpdateAvailable/UpstreamBaseVersion 供 UI 提示),PerformUpdate/Rollback/ListRollbackVersions/RollbackToVersion 一律返回 ErrDownstreamUpdateManaged(DOWNSTREAM_UPDATE_MANAGED),防止下游构建把自己升级成丢失下游特性的官方二进制;parseVersion 复用该函数剥后缀。宿主发布通道安全机制。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (729 lines, 2 chunks). git diff aea725f: +ErrDownstreamUpdateManaged, +UpdateStrategy/UpstreamBaseVersion/UpstreamUpdateAvailable on UpdateInfo, downstream gates at PerformUpdate (~L173), Rollback (~L295), ListRollbackVersions (~L325), RollbackToVersion (~L349), strategy-aware HasUpdate in fetchLatestRelease (~L442-L451) and getFromCache (~L644-L655), parseVersion via updateStrategyForVersion, new updateStrategyForVersion (L702-L729).", - "Consumers: frontend/src/api/admin/system.ts:18-19 and stores/app.ts:253/273 read update_strategy/upstream_base_version; matches the codexrip release flow (annotated codexrip tags).", - "Security properties (validateDownloadURL HTTPS+host allowlist, '..' rejection, 500MB LimitReader, same-dir atomic rename) are upstream-identical; delta only adds refusal gates before them.", - "Static review only; version strings like 0.1.166-rc1 fall through to strategy upstream with base 0.1.166 (suffix not a managed channel)." - ] - }, - { - "path": "backend/internal/service/update_service_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "3bd912c9b7d7a35956d00c57e21270a380dbe38f04c0f42d8f059b609c29dc6f", - "review_fingerprint": "3bd912c9b7d7a35956d00c57e21270a380dbe38f04c0f42d8f059b609c29dc6f", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "UpdateService 单测(//go:build unit)。下游新增三项:下游版本(refusal-recovery.3 / v...-codexrip.1)返回 UpdateStrategy=downstream、UpstreamBaseVersion=官方基线且 HasUpdate=false;官方基线前进时 UpstreamUpdateAvailable=true 但 HasUpdate 仍 false,且 PerformUpdate/Rollback/ListRollbackVersions/RollbackToVersion 全部 ErrorIs ErrDownstreamUpdateManaged;compareVersions 把下游后缀视为同基线。其余回滚列表过滤/排序/拒绝目标用例为上游既有。证明 update_service.go 的下游发布通道保护。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review (235 lines). git diff aea725f: +TestUpdateServiceDownstreamVersionUsesOfficialBaseWithoutOfferingUpdate, +TestUpdateServiceDownstreamWaitsForManagedSyncWhenOfficialBaseAdvances, +TestCompareVersionsParsesDownstreamPatchSuffix (L72-L118).", - "Stubs: updateServiceCacheStub / updateServiceGitHubClientStub (DownloadFile/FetchChecksumFile panic if reached), so the gates are proven to short-circuit before any download.", - "Asserts DOWNSTREAM_UPDATE_MANAGED on all four mutating/list entry points and strategy fields on CheckUpdate output.", - "Test read statically, not executed." - ] - }, - { - "path": "backend/internal/service/upstream_models.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "6fb2492caa693d8766c63433271b1c9801bbb9636429379f04a684dfbf4cbc68", - "review_fingerprint": "6fb2492caa693d8766c63433271b1c9801bbb9636429379f04a684dfbf4cbc68", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "跨平台上游模型清单同步(AccountTestService):按平台构建 /v1/models 探测请求(OpenAI/Anthropic/Gemini/Grok/Antigravity,含 OAuth 与 API key 差异)、models.dev 注册表补齐能力元数据、按模型完整才落库。下游相对上游 aea725f +98/-16:(1) SyncUpstreamModelCatalog 新增原始上下文容量观测——ParseUpstreamModelContextCapacities 只保留上游确实声明的值,mergeObservedModelContextCapacity 保证部分观测不清空同源已知上限且继承字段沿用旧 ObservedAt,快照带 SourceIdentity(getter 在源变更时拒读),catalog 增加 CapacityRows;两类 Extra 更新合并为一次 UpdateExtra,且仅 account.ID>0 才持久化;(2) buildOpenAIOAuthUpstreamModelsRequest 改用 resolveCodexOutboundIdentityForAccountContext/enforceCodexIdentityHeadersForAccountContext(按账号上下文与 override UA 解析并可返回错误);(3) extractUpstreamModelCatalog 改为容错解码,字段类型错误不再丢弃整条模型,容量字段交给独立严格解析器。均为宿主网关协议/容量机制,无插件侧重复执行体。仅静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "1622 行全读;diff 锚点:L51-L55 CapacityRows 字段、L228-L258 容量观测与 retainedIDs 合并、L318-L330 合并后的单次 UpdateExtra、L350-L365 mergeObservedModelContextCapacity(含 CapacityBasis 判定)、L1163-L1178 codex 身份上下文化、L1363-L1380 容错解码 + ParseUpstreamModelContextCapacity。", - "调用链:ParseUpstreamModelContextCapacit*/BuildAccountModelContextCapacityRows/SourceIdentity 定义于 service/model_context_capacity.go 与 _parser.go(readModelContextCapacitySnapshot L344 在 SourceIdentity 不匹配时返回 nil,防跨源继承——与容量测试 L92-L108 一致);codex 身份助手位于 openai_codex_identity.go L288 与 plugin_codex_identity.go L57。", - "No production behavior edit or test execution; capacity merge and identity enforcement were verified by reading only." - ] - }, - { - "path": "backend/internal/service/upstream_models_capacity_sync_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b9e7dc6c1a3f92dae0b1a5abb373cb693d20e5c40b54fb052125579030421f98", - "review_fingerprint": "b9e7dc6c1a3f92dae0b1a5abb373cb693d20e5c40b54fb052125579030421f98", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "下游新增测试(上游无此文件),证明 SyncUpstreamModelCatalog 容量同步的五条不变量:容量观测独立落库、不得替换能力快照或管理员 ModelContextOverrides(L25-L45);account.ID=0 的预览绝不持久化但仍返回 CapacityRows(L47-L54);部分刷新继承旧值时保留真实观测时间、无效容量字段(max_output_tokens:\"invalid\")按零丢弃、已下线模型从快照剔除(L56-L74);仅输出上限刷新不清已知 context(L76-L90);base_url 变更(SourceIdentity 变化)后不得继承旧源上限(L92-L108);extractUpstreamModelCatalog 对类型错误的可选容量字段保持其余能力可用(L110-L119)。逐条对应 upstream_models.go 下游 delta。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "121 行全读;git ls-tree aea725f 无此路径,整文件为下游 delta。锚点:newCapacitySyncFixture 双响应桩(第二响应 502 阻断注册表补齐路径,L13-L23)。", - "源变更用例的通过依赖 model_context_capacity.go readModelContextCapacitySnapshot L344 的 SourceIdentity 校验(已核对),并非 SyncUpstreamModelCatalog 内显式比较。", - "No test execution; statically read only." - ] - }, - { - "path": "backend/internal/service/upstream_models_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9449b27748eb4c28893d621f28170f0a2306738069a8bccb0ba984bad2002e6a", - "review_fingerprint": "9449b27748eb4c28893d621f28170f0a2306738069a8bccb0ba984bad2002e6a", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "上游模型同步主测试(1189 行):URL 拼装(v1/v1beta/antigravity 网关)、各平台请求头(Grok OAuth CLI 头仅发给可信代理主机、账号 header override 不泄漏给 models.dev 注册表请求)、ID 提取(Grok 多字段候选顺序、slug 清单)、registry 匹配(官方 openai 无 api 字段按已知主机回落、仿冒主机拒绝)、能力落库策略(完整才存、部分批次告警、媒体模型不阻断、mapping 目标补齐、404/405 才用已配置模型)。下游相对上游仅 +4/-2:两处 registry 失败用例的断言由 require.Nil(repo.updates) 改为容量键仍在、能力键不在——证明下游把容量观测与能力快照拆分持久化后,注册表失败不再阻止模型 ID/容量落库,也仍不覆盖既有能力快照。仅静态阅读,未执行测试。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S23-svc-gateway-billing-3-review.json", - "1189 行全读;diff 锚点:TestSyncUpstreamModelCatalogDoesNotOverwriteSnapshotWhenRegistryFails L772-L773 与 TestSyncUpstreamModelCatalogDoesNotPersistPartialMetadataWhenRegistryFails L800-L801 的 NotContains(UpstreamModelMetadataExtraKey)+Contains(UpstreamModelContextCapacitiesExtraKey)。", - "其余用例(Grok OAuth 头、models.dev 主机回落、Astra 部分刷新保留 CodexToolCapabilities 等)与上游一致,此处仅作为被测机制的静态阅读证据,不宣称由下游新增。", - "No test execution; statically read only." - ] - }, - { - "path": "backend/internal/service/usage_billing.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "199b032d8e36c051078b206bbaa6f01d891878ad63646efc8f83b3034f82cc6e", - "review_fingerprint": "199b032d8e36c051078b206bbaa6f01d891878ad63646efc8f83b3034f82cc6e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "宿主计费机制:UsageBillingCommand 的幂等指纹与金额量化(NUMERIC(20,8) half-away-from-zero,量化在指纹之后以保证升级前后同 request_id 重试指纹稳定)、批量图片余额 hold 命令、UsageBillingRepository 接口。下游唯一改动:UsageBillingApplyResult 新增 OwnerAccountID int64,由 repository/usage_billing_repo.go 在 Apply 的两个分支填充并被 repo 测试断言(非 dead)。generic 宿主 quota/billing。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: single '+OwnerAccountID int64' field on UsageBillingApplyResult (L167).", - "QuantizeUsageBillingAmount uses shopspring/decimal Round(8) to match PostgreSQL float8->numeric; buildUsageBillingFingerprint sha256 over normalized fields incl optional payload hash.", - "OwnerAccountID is set by repository/usage_billing_repo.go:50/53 and asserted in repository/usage_billing_owner_test.go — live, not a dead field.", - "No secrets logged; billing execution lives in the repository (other slice)." - ] - }, - { - "path": "backend/internal/service/usage_commit_observer_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "63051b0331b0d9b815599ce547ba88435f81c25e1c4c71f055ac9eb1ec0b34db", - "review_fingerprint": "63051b0331b0d9b815599ce547ba88435f81c25e1c4c71f055ac9eb1ec0b34db", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "本轮明确授权扩展的185行新测试;完整审阅并实际红/绿运行两网关8场景矩阵。", - "evidence": [ - "GatewayService和OpenAIGatewayService各验证sync成功、best-effort成功、普通失败后sync成功、drop后sync成功、sync失败、drop且sync失败、重复CAS、CAS失败。", - "阻塞fake-logrepo由channel控制;writer释放前不许observer,成功后只许一次并携带account701且QuotaActivity receipt已logged。", - "所有场景断言billing Apply恰好一次,成功/失败日志保留logged与gap语义;失败/drop不误通知。只有合成数据和本地定价计算,无DB或模型调用。" - ] - }, - { - "path": "backend/internal/service/wire.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "40732852aa41864f596251c76252c4e2c555f857ee6bb5103619374d219552d1", - "review_fingerprint": "40732852aa41864f596251c76252c4e2c555f857ee6bb5103619374d219552d1", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "service 层 Wire DI 装配(ProviderSet 与各 Provide* 构造/启动函数)。下游改动全是装配层:新增 ProvideBusinessSystemPromptService/RemoteSkillRegistry*(prompt-skills 领域宿主服务)、ProvideOpenAIGatewayService(注入 business prompt policy)、ProvideCindyHealthService/ProvideCindyBalanceProbeService(cindy-provider 领域宿主服务并回注 gateway 协调器)、ProvideImageStudioArtifactStore+NewImageStudioService(image-tools)、ProvideCodexClientIdentityBackfillService(codex-runtime)、NewQuotaActivityService/NewAccountTrafficObserver/NewAccountJobService、ProvidePluginManager 替代 NewPluginManager,以及把 QuotaActivityService 注入 OpenAIQuotaService/AccountTestService/OpsService、UsageCache+UsageCommitObserver 注入两个网关。所有被引用构造函数与接口均存在;UsageCommitObserver 由 cmd/server/wire.go 提供。这些插件领域服务本身仍驻留 core 的归属问题属其各自 slice,本文件只是宿主 DI 胶水。仅静态阅读,未执行(未运行 wire gen)。", - "evidence": [ - "Full-file static review (1190 lines, 3 chunks). git diff aea725f: +path/filepath import; new providers L51-L155; ProvideImageStudioArtifactStore L216-L222; activity into ProvideOpenAIQuotaService (L301/L305), ProvideAccountTestService (L381/L397), ProvideOpsService (L858/L881); usage cache/observer into ProvideAccountUsageService (L344-L351); ProvideCodexClientIdentityBackfillService L534-L539; ProviderSet edits (NewAccountJobService, prompt/skill/gateway/cindy providers, image studio + wire.Bind ImageStudioFileStorage, NewQuotaActivityService, NewAccountTrafficObserver, ProvideCodexClientIdentityBackfillService, ProvidePluginManager).", - "Consistency: rg confirms every referenced constructor exists (plugin_provider.go ProvidePluginManager, account_job.go, account_traffic_observe.go, openai_codex_client_identity.go, image_studio_artifact.go, image_studio_job_service.go, quota_activity.go, business_system_prompt_service.go, remote_skill_registry*.go, cindy_health.go, cindy_balance_probe_service.go); UsageCommitObserver func type (account_usage_service.go:132) provided by cmd/server/wire.go:91.", - "Injected activity is read by OpenAIQuotaService (quota_estimate.go:76/147, account_usage_service.go:869) and AccountTestService (account_test_service.go:395) but NOT by OpsService — see ops_service.go finding (wire.go L881 is the write-only assignment).", - "Plugins (plugins/prompt-skills, image-tools, cindy-provider) hold policy/catalog modules over extensionv1 types; the wired core services are host executors — no DI-level duplication. Static review only; wire_gen not regenerated or compiled." - ] - }, - { - "path": "backend/internal/service/wire_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "a535f7a13729b6dfc0ce043f670dceafeca189a0a84020392227eef445d17e03", - "review_fingerprint": "a535f7a13729b6dfc0ce043f670dceafeca189a0a84020392227eef445d17e03", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "ProvideTimingWheelService 的 DI provider 单测:注入桩使 newTimingWheel 返回 error 时 provider 返回 (nil,err),成功时返回可用服务。下游改动仅在成功用例的 nil 守卫后加 return(t.Fatal 后静态安全,无行为变化)。被测主体是 core 的 timing wheel 调度原语 provider。仅静态阅读,未执行。", - "evidence": [ - "Full-file static review. git diff aea725f: single '+return' after t.Fatalf svc==nil guard.", - "Overrides package var newTimingWheel (go-zero collection.TimingWheel) to force构造失败;asserts svc==nil on error and Stop() on success.", - "Subject: core DI provider for the generic timing-wheel scheduling primitive.", - "Delta is lint hardening only; test read statically, not executed." - ] - }, - { - "path": "backend/internal/testextensions/fixtures.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "d05027e7e33ca849c73c637e5ea432e9ec33d3e76f43578bfbbf815e0a5d4fc7", - "review_fingerprint": "d05027e7e33ca849c73c637e5ea432e9ec33d3e76f43578bfbbf815e0a5d4fc7", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "下游新增的测试夹具包(仅被宿主测试导入:rg 'internal/testextensions' 在非测试文件无命中;go.mod 以 replace 指向 ../plugins/*):把七个插件域的真实 Go 模块(cindyprovider/catalog、codexruntime/profile+recovery、accounttools/policy、adminobservability/policy、imagetools/policy、modelpolicy/catalog、promptskills/policy)以进程内方式注入 service.ConfigureProcessExtensionServices,按 Capability=recovery 或操作前缀(codex.identity.*、codex.transport.plan、observability.*、image.*、cindy.*、taxonomy./test./import./tools.describe、prompt./skills.)分发到对应模块,其余返回 ErrExtensionOperationDisabled;image.*/cindy.* 用 service.LegacyImageToolsConfig/LegacyCindyProviderConfig 初始化。Install/InstallImageTools 是确定性契约夹具,不是生产装配(生产走 ProvidePluginManager 的签名插件进程)。作为扩展宿主测试支撑材料记为 reference;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L24-L73 operations.InvokeOperation 按能力/前缀分发;L74-L78 Install/InstallImageTools 调用 service.ConfigureProcessExtensionServices(catalog.New(), ...)。", - "L1-L3 包注释声明仅测试导入;backend/go.mod L5-L13 replace 指向本仓库 plugins/ 目录;宿主侧 service.LegacyImageToolsConfig/LegacyCindyProviderConfig 为插件默认配置的核心持有点(属其他切片评估)。", - "静态阅读,未执行测试或构建。" - ] - }, - { - "path": "backend/internal/testutil/stubs.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "1ca81932a26f029580cc42efd875c4bf50d00ae24c9873ef5a21641883ffb735", - "review_fingerprint": "1ca81932a26f029580cc42efd875c4bf50d00ae24c9873ef5a21641883ffb735", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-quota-and-protocol", - "reason": "单元测试共享桩(//go:build unit,不进生产构建):ConcurrencyCache、GatewayCache、SessionLimitCache 三个接口的零值实现,含编译期接口断言。下游 delta 仅为 StubGatewayCache 补 DeleteSessionAccountIDIfMatches(ctx, groupID, sessionHash, expectedAccountID) (bool, error) 返回 (false, nil):下游 service.GatewayCache 接口新增该比较删除方法(gateway_service.go L476-L479,供 openai_sticky_compat.go 与 openai_ws_state_store.go 在粘性会话解绑时只删除仍指向预期账号的绑定;上游无此方法),桩需实现以满足 var _ service.GatewayCache 断言。不证明任何修复;静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L106-L108 新增桩方法(diff 仅此 3 行);L90 编译期断言 var _ service.GatewayCache = StubGatewayCache{}。", - "接口定义 service/gateway_service.go L476-L479;调用点 service/openai_sticky_compat.go L219、openai_ws_state_store.go L338;git grep 上游无 DeleteSessionAccountIDIfMatches。", - "静态阅读,未执行测试或构建。" - ] - }, - { - "path": "backend/internal/web/agent_route_ownership_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b95a53865cb1ca32050f828a259ca5c59ffce45204cdceb4c32dad4d8d48499b", - "review_fingerprint": "b95a53865cb1ca32050f828a259ca5c59ffce45204cdceb4c32dad4d8d48499b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "下游新增测试(embed 构建标签),证明内嵌前端不再拦截 API:TestAgentRegisteredAPIRoutesOwnTheirResponses 对 legacy ServeEmbeddedFrontend 与 settings 注入版 FrontendServer.Middleware 两种以 router.Use 挂载的方式,POST /chat/completions、/embeddings、/messages/count_tokens、/tts、/future-api/execute(不在任何前缀白名单内)都必须到达已注册 handler 并得到 JSON 401;TestAgentFrontendFallbackUsesRouteTableAndMethods 用 RegisterFrontendFallback 验证:已注册路径的错误方法返回 JSON 405、API 命名空间(chat/future-api/v1)下未知路径与非 GET/HEAD 的未知路径返回 JSON 404、//chat/completions 归一化后 404,而 /、/dashboard(GET/HEAD)返回 text/html。证明 embed_on.go(FullPath/方法判定)、frontend_routes.go 与 router.go 的下游修复;依赖 embed_test.go 的 mockSettingsProvider。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L14-L39 两种挂载方式 × 五条路径的矩阵,断言 called、401、Content-Type 含 application/json;L41-L77 11 组 method/path/status/html 表。", - "对应实现 web/embed_on.go L92/L314(c.FullPath()!=\"\" 或非 GET/HEAD 放行)与 web/frontend_routes.go L15-L34;生产装配见 router.go L95。", - "静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/web/embed_on.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "712e9c6d13a53475e4c70615fbfeae81f56f84eabc1f6343e296da560d93eba8", - "review_fingerprint": "712e9c6d13a53475e4c70615fbfeae81f56f84eabc1f6343e296da560d93eba8", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "embed 构建下的内嵌前端服务:FrontendServer(settings 注入、HTMLCache/ETag、nonce 占位替换、站点标题/favicon 注入、data/public 覆盖目录、指纹资源缓存头)与 legacy ServeEmbeddedFrontend。下游 delta 三处:Middleware 与 ServeEmbeddedFrontend 的跳过条件在原有路径前缀白名单之外,增加 c.FullPath()!=\"\"(已匹配路由)或非 GET/HEAD 即放行,修正 SPA 以全局中间件挂载时抢先吞掉未列入前缀表的 API(如 /chat/completions、/tts)的问题;shouldBypassEmbeddedFrontend 新增 /skills/ 前缀,为 router.go 挂载的 RemoteSkill 公开路由让路。与 frontend_routes.go 的 NoRoute 兜底配合时,FullPath 判定属纵深防御。其余注入/缓存逻辑与上游一致。静态阅读,未执行;未做浏览器验证。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L92 与 L314 跳过条件(diff:由仅 shouldBypassEmbeddedFrontend(path) 改为 FullPath/方法/前缀三重判定);L355-L371 前缀表新增 L363 /skills/。", - "L145-L202 serveIndexHTML 缓存、304 与 nonce 替换,L204-L218 injectSettings,L252-L269 safeImageURL 仅允许 http(s)/根相对/data:image,与上游相同。", - "静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/web/embed_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8f360de4cad4716b36a9da9b742ead3ae83eacccc5970eda8ebc53b5a38c2c3c", - "review_fingerprint": "8f360de4cad4716b36a9da9b742ead3ae83eacccc5970eda8ebc53b5a38c2c3c", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "embed 构建下的内嵌前端测试集(上游既有):injectSiteTitle/injectSiteFavicon 的替换、HTML 转义与 unsafe URL 拒绝,nonce 占位替换,FrontendServer.injectSettings/serveIndexHTML 的缓存、ETag/304、Cache-Control、设置获取失败回退,InvalidateCache,覆盖文件不带 immutable 缓存头,Middleware 与 legacy 对 API 路径放行、SPA 与静态文件服务,视频裸路径 bypass,HTMLCache 行为与基准测试。下游 delta 三处:两处静态文件用例由 /logo.png 改为 /logo.svg 并断言 image/svg+xml(适配下游 dist 资源);新增 TestEmbeddedFrontendBypassesRemoteSkillRoutes 断言 /skills/... 三条路径被 shouldBypassEmbeddedFrontend 放行。新增用例证明的是 embed_on.go 的 /skills/ 前缀胶水而非修复;其余断言为上游内容。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L653-L658 与 L748-L752 logo.svg / image/svg+xml(diff 改动);L692-L700 新增 /skills/ bypass 用例(diff 新增)。", - "L207-L217 mockSettingsProvider 被 agent_route_ownership_test.go 复用;L512-L679 Middleware 用例先 router.GET(path) 注册再请求,故在下游 FullPath 判定下同样放行。", - "静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/web/frontend_routes.go", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "31c41dc6df5a7aa872205c9fc7127f9e2d817eb42bd4e8c1f5c2be54f4cb0936", - "review_fingerprint": "31c41dc6df5a7aa872205c9fc7127f9e2d817eb42bd4e8c1f5c2be54f4cb0936", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core", - "reason": "下游新增:RegisterFrontendFallback 在全部 API 路由注册完成后调用,从 router.Routes() 收集每条路由的首段作为 API 命名空间集合,开启 HandleMethodNotAllowed 并以 JSON(invalid_request_error/method_not_allowed)响应 NoMethod;NoRoute 中若 frontend 为空、请求路径首段落在 API 命名空间、或方法非 GET/HEAD,则返回 JSON 404,否则才交给 SPA handler;frontendRouteNamespace 用 path.Clean 归一化(//chat/completions → chat)。这把前端从全局前置中间件改为路由表驱动的兜底,消除手工前缀白名单漂移的风险。已核对 frontend/src/router 的顶级段(admin/auth/payment/login/usage/keys/model-plaza/image-studio/setup 等)与根级 API 命名空间(alpha/chat/custom-voices/embeddings/images/messages/models/realtime/responses/stt/tts/videos/web_search/x_search 及 api/v1/v1beta/v3/backend-api/antigravity/health/skills/contents)无重叠,且主路由器未注册 /setup API,当前不会误伤 SPA 深链接;若日后新增与 SPA 页面同首段的根级 API 路由,该页面直接访问会变为 JSON 404,属需注意的耦合。静态阅读,未执行;未做浏览器验证。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L15-L34 RegisterFrontendFallback(命名空间集合、NoMethod 405、NoRoute 三重判定);L36-L40 frontendRouteNamespace;L42-L46 frontendRouteError。", - "调用点 server/router.go L95(registerRoutes 之后);被 web/agent_route_ownership_test.go L48 直接测试;rg 核对 frontend/src/router 顶级 path 与 gateway.go rootRoute 命名空间无交集。", - "静态阅读,未执行测试。" - ] - }, - { - "path": "backend/internal/web/testdata/agent_cache_fixture.js", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f6e7f0325a9154918d4e63e3d6ef57c646be29d8e930db0f5210894a63f58dfd", - "review_fingerprint": "f6e7f0325a9154918d4e63e3d6ef57c646be29d8e930db0f5210894a63f58dfd", - "review_status": "reviewed", - "decision": "reference", - "owner": "core", - "reason": "下游新增的 47 字节测试数据文件,仅一行 `export const agentProtocolCacheFixture = true;`。rg 全仓库(含 backend/internal/web 各测试)未发现任何引用该文件名或导出常量的代码,Go 测试也不会加载 .js testdata;属迁移遗留的孤儿夹具,无运行时影响。记为 reference,并在 findings 登记为 low(建议删除或补上使用它的测试)。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L1 唯一内容;rg 'agentProtocolCacheFixture|agent_cache_fixture' 仅命中文件自身。", - "无生产或测试引用,不影响构建;静态阅读,未执行。" - ] - }, - { - "path": "backend/migrations/192_codexrip_account_taxonomy.sql", - "candidate_owner": "account-tools", - "role": "source", - "present": true, - "content_sha256": "bde71a4d2c4f5015054ec86a4a61706678ad10b6b1521625323ed305efdcf739", - "review_fingerprint": "bde71a4d2c4f5015054ec86a4a61706678ad10b6b1521625323ed305efdcf739", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Management-only folders/tags are separate from routing groups. Names have unique normalized storage; folder references are RESTRICT, tag binding primary key prevents duplicate relationships and deletes cascade only the corresponding relation. The migration adds storage/indexes and never rewrites account routing, credentials or scheduler fields.", - "evidence": [ - "Complete SQL read; current classification deletion service separately enforces scope before these global FK effects.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/194_business_system_prompts.sql", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "19758f2053fd7092606f8a8493e087e0dd46f8265841bb8df2981c1e2f55b583", - "review_fingerprint": "19758f2053fd7092606f8a8493e087e0dd46f8265841bb8df2981c1e2f55b583", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Versioned template content and body hashes are host-owned immutable data. Runtime singleton starts fully disabled, with same-template version FK/pair constraint and monotonic positive revision. Update/delete triggers forbid content changes/deletion while publish metadata remains mutable; ON CONFLICT leaves an existing runtime row unchanged.", - "evidence": [ - "Complete SQL read including both trigger bodies, composite FK and initial disabled row.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/195_business_system_prompt_skill_bundles.sql", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "e05ae5add09353bf87014ca52477b1ba1a7f48eba7538299a6d2e61c6e4e8ab8", - "review_fingerprint": "e05ae5add09353bf87014ca52477b1ba1a7f48eba7538299a6d2e61c6e4e8ab8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Adds historical composition/bundle references and backfills only the captured is_seed/slug/version/body-hash/byte-length combination that was still inline without bundle identity. Existing administrator-created or already-attributed versions remain unchanged. The replaced immutability trigger includes the new composition metadata.", - "evidence": [ - "Complete SQL predicates and trigger read. Historical file byte-identical to current production source baseline; no new applied migration rewrite.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/196_business_system_prompt_remote_skill.sql", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "88667da4408f4f28e2788a74f24f730387d781dff7a3e050a3a1481e1c12207f", - "review_fingerprint": "88667da4408f4f28e2788a74f24f730387d781dff7a3e050a3a1481e1c12207f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Historical explicit v1 seed replacement: computes embedded UTF-8 hash/length, requires exact seed cardinality and previous hash/bytes/bundle identity, and aborts unexpected state. It temporarily removes the immutable-content trigger inside the migration transaction, replaces only that version, restores the trigger and resets the relevant old runtime switches. This is not a new v0.2.7 cleanup step or permission to rerun it.", - "evidence": [ - "Embedded body independently decoded to 7045 bytes and cbf75cc85cd77860e53d06820e7120802d83c069e9d24b48715711acc15893c6, equal to the SQL guard; complete SQL logic read with the long literal elided from output.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/197_remote_skill_registry.sql", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "56848128789bb44ecb8e6cf02775b105b80b3a00d09645bd677a3801e8b7b9bf", - "review_fingerprint": "56848128789bb44ecb8e6cf02775b105b80b3a00d09645bd677a3801e8b7b9bf", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Introduces immutable bounded remote skill candidates, a separate singleton active pointer, and queued/running/succeeded/failed sync history. Candidates reference fixed source/hash shapes and content limits; jobs cannot promote the active pointer by insert. Version content/update and delete protection are explicit, with runtime/candidate FK RESTRICT preserving referenced data.", - "evidence": [ - "Complete tables/indexes/trigger SQL read. New rows default to no active candidate and do not execute any remote scripts.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/198_business_system_prompt_codex_skill_hybrid.sql", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "69086b65cdbd922e75eb924eafae0e519409d6767a42f1d3a79b5c2152872535", - "review_fingerprint": "69086b65cdbd922e75eb924eafae0e519409d6767a42f1d3a79b5c2152872535", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Historical remote-to-hybrid seed replacement is constrained by exact captured old and new prompt fingerprints. Registry upgrade locks the singleton pointer and only replaces an exact prior release bundle identity; unexpected or administrator-published shapes raise instead of being overwritten. Both prompt trigger restoration and composition constraints remain. No new run or modification is performed this task.", - "evidence": [ - "Embedded body independently decoded to 9587 bytes and 0b717f086b1bf25e8300e9f26578ee95cf6f74d5601c06b9f9e493aa8939b0a7; exact old/new bundle SHA/count/size predicates and transaction logic read.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/199_business_system_prompt_managed_source.sql", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "794885b3ce80184445aefaa14549d39f3e259df7e568ebd1ad5bb13bed03a2ef", - "review_fingerprint": "794885b3ce80184445aefaa14549d39f3e259df7e568ebd1ad5bb13bed03a2ef", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Adds nullable managed-source identity with partial uniqueness, all-or-none source provenance fields and commit/version/artifact/license hash shapes. Trigger protects managed_source against subsequent changes and expands immutable version protection to every new source field. Does not seed or publish content itself.", - "evidence": [ - "Complete structural SQL and trigger field list read; startup/plugin policies remain separate from durable constraints.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/200_remote_skill_sources_and_legacy_cleanup.sql", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "1be931539c703b9189033545d11662aa1cad54e88b1b04a3bea3fff5df0bde95", - "review_fingerprint": "1be931539c703b9189033545d11662aa1cad54e88b1b04a3bea3fff5df0bde95", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Historical source attribution and retired-mode cleanup is unchanged from the production baseline. It first attributes legacy candidates, constrains sources, locks/validates any active retired prompt against one exact hybrid replacement, and refuses an unresolved active reference. Only then removes retired remote_skill/offline_bundle prompt versions and now-unreferenced templates, restores deletion protection and narrows allowed modes. It never deletes skill bundle rows or inline/hybrid versions; the immutable runner skips the already-recorded file on normal upgrade.", - "evidence": [ - "Complete SQL read including all DELETE predicates, temporary old-template set, singleton lock and replacement cardinality. Do not reinterpret this historical migration as an authorized new general-purpose cleanup.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/200_remote_skill_sources_and_legacy_cleanup_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "72935ab38037bfbc4faf4dbd40d64577daf18fdc44e992cbb0d8c40319e9d1fb", - "review_fingerprint": "72935ab38037bfbc4faf4dbd40d64577daf18fdc44e992cbb0d8c40319e9d1fb", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "Full test body read: lowercases embedded SQL, requires source/identity/active-reference/retired-mode guard fragments, forbids three specific deletion strings. This is a static text contract, not proof of transactional behavior or every possible equivalent destructive SQL statement.", - "evidence": [ - "Current test body read, no new execution because source and tested SQL are unchanged; prior passing migrations are not rerun.", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/201_remote_skill_paired_candidates.sql", - "candidate_owner": "prompt-skills", - "role": "source", - "present": true, - "content_sha256": "34daf7dc9ddc74c7a8dacb0a1ee2369fdd9cb0fc299a15b2bb8a4e0e012cc7fe", - "review_fingerprint": "34daf7dc9ddc74c7a8dacb0a1ee2369fdd9cb0fc299a15b2bb8a4e0e012cc7fe", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-data-and-migrations", - "reason": "Historical storage-shape transition records paired raw/effective prompt bodies and hashes, adds nullable legacy transition fields plus RESTRICT active prompt references, constrains source roots and byte limits, and advances sequences without reducing existing values. It removes obsolete metadata columns but does not delete rows in SQL. GUC-gated deletion triggers remain historical definitions; the present application has no internal Go DELETE/cleanup-GUC path for these version tables. The comment promising startup removal is historical, not current behavior.", - "evidence": [ - "Complete 201 SQL read; source rg found no sub2api.remote_skill_cleanup or version-table DELETE statement in backend/internal/*.go. No old migration bytes altered.", - "git diff 65a82d9a8f079f389f08e092d318a663123095e9 -- the nine named migration files: no changes", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/201_remote_skill_paired_candidates_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "921551ac74af7d73a2aa484b3f44cb23677e9adde01b4d5b90fa2b5ff21308ab", - "review_fingerprint": "921551ac74af7d73a2aa484b3f44cb23677e9adde01b4d5b90fa2b5ff21308ab", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "Full test body read: lowercases embedded SQL and checks paired-body/source/hash/sequence/managed-source/cleanup guard fragments, forbids legacy origin/descriptor/bootstrap additions and three legacy column additions/selects. It does not execute PostgreSQL or prove historical data transformation.", - "evidence": [ - "Current test body read, no new execution because source and tested SQL are unchanged; prior passing migrations are not rerun.", - "artifacts/evidence/v027-historical-prompt-storage-review.json" - ] - }, - { - "path": "backend/migrations/202_add_cindy_balance_insufficient_at.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "d6fcfe31e8c7040c0ae2c216cc2331e4b11b402a4e8ca53c6373a1e1f02e1141", - "review_fingerprint": "d6fcfe31e8c7040c0ae2c216cc2331e4b11b402a4e8ca53c6373a1e1f02e1141", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整3行;这是持久余额标记的加列机制而非插件当前配置或可随意重放的数据重置。", - "evidence": [ - "只ADD COLUMN IF NOT EXISTS cindy_balance_insufficient_at TIMESTAMPTZ NULL;NULL表示没有耗尽标记,不改status/schedulable或现有凭据。", - "列仍被后续health/schema和runtime读取;已发布字节必须保留,不能因插件拆分删除。" - ] - }, - { - "path": "backend/migrations/207_codexrip_restore_cindy_openai_defaults.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "cfb050ee58e69638b73d9329bed9ba87584bcce4094669ac3c9cdea96d5958d5", - "review_fingerprint": "cfb050ee58e69638b73d9329bed9ba87584bcce4094669ac3c9cdea96d5958d5", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整27行;历史上把精确OpenAI+Laxa API key改回direct/passthrough,当前后继208/209已分别更新这两个值。", - "evidence": [ - "正向WHERE同时限定platform/type、base_url JSON string、大小写/空格规范化后的两个精确root;missing/null URL不满足正向条件。", - "extra以COALESCE从SQL NULL构造对象;只写两个Extra键,不改credentials/status/schedulable/updated_at;故包括soft-deleted严格identity但不恢复账号启用。", - "若已记账,运行器按文件名+checksum跳过,不会在本次重设管理员后来选择;208改prompt hash、209改search bridge是明确后续修正。" - ] - }, - { - "path": "backend/migrations/208_codexrip_use_cindy_prompt_cache_hash.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "c9eacd29e55d9d29ce286760811a0a0a9138dbd3027f5323ba2ec83daac7085e", - "review_fingerprint": "c9eacd29e55d9d29ce286760811a0a0a9138dbd3027f5323ba2ec83daac7085e", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整19行;专门覆盖207的prompt-cache旧默认,不应把历史迁移当成当前业务开关。", - "evidence": [ - "只将严格OpenAI API key根地址的openai_prompt_cache_key_mode设为sha256_64,IS DISTINCT FROM避免相同值再写。", - "不同时改search/responses模式、凭据或调度状态;其数据演进含义由当前插件/服务读取策略决定,不能通过重放迁移强制用户配置。" - ] - }, - { - "path": "backend/migrations/209_codexrip_restore_cindy_alpha_search_bridge.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "0bced665cf9a296939f949b51251421abf8d09ee4807f8343fac13e57d64995c", - "review_fingerprint": "0bced665cf9a296939f949b51251421abf8d09ee4807f8343fac13e57d64995c", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整20行;历史上独立把严格Cindy search模式从direct迁到responses_web_search。", - "evidence": [ - "正向类型/精确根URL匹配,且只改openai_alpha_search_mode;不清空prompt-cache或其他extra键。", - "不写status/schedulable/credentials/updated_at、不探测上游;对应unit fixture检查这些边界,但本轮未运行。" - ] - }, - { - "path": "backend/migrations/210_codexrip_reset_legacy_cindy_balance_markers.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "3d835f6cd20604b4117b73584c69541e2edce09af7c361b5ddb7e5d13373842a", - "review_fingerprint": "3d835f6cd20604b4117b73584c69541e2edce09af7c361b5ddb7e5d13373842a", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整25行;一次性收窄旧402/不完整429遗留标记,策略随后由211/213继续演进,不能再当当前健康校准入口。", - "evidence": [ - "仅非NULL且严格旧OpenAI+Laxa身份的marker可清;标记前后2分钟内存在精确status429/type budget_exceeded/code字符串429则保留。", - "只有cindy_balance_insufficient_at被SET NULL,不动管理员status/schedulable,包含软删除对象。", - "SQLTrim checksum ec98aa…与既有测试内已发布固定值一致;测试中'已应用生产'文字只是历史断言,不等同本轮读取生产ledger。" - ] - }, - { - "path": "backend/migrations/211_codexrip_restore_exact_cindy_budget_markers.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "04899daf9d253f9592179872e0b3d61b0ce2e4f8085bf65c3af2482337cbf12a", - "review_fingerprint": "04899daf9d253f9592179872e0b3d61b0ce2e4f8085bf65c3af2482337cbf12a", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整49行;历史修复210缺少结构化列时漏掉真实上游JSON证据的情况,但单信号永久标记策略后来由213退役。", - "evidence": [ - "CASE WHEN upstream_error_detail IS JSON才转jsonb;要求HTTP429和error.type/error.code都为string且精确匹配,不按消息文本/numeric429推断。", - "按账号取最新精确信号,仅为marker仍NULL且之后无usage_log的严格未删除Cindy账号恢复;不覆盖已标记时间。", - "213随后清掉该历史单信号阶段严格身份标记,所以不能把211恢复行为当作今天的自动重试/health恢复规则。" - ] - }, - { - "path": "backend/migrations/212_codexrip_materialize_cindy_group_identity.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "e197fa7ce94bcefc58a96769fab4ae8a0de0c41b3d7781fc6f775ac196e9cb23", - "review_fingerprint": "e197fa7ce94bcefc58a96769fab4ae8a0de0c41b3d7781fc6f775ac196e9cb23", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整97行;在DB中保持账号identity/组成员变更到跨实例auth缓存失效的持久机制,236后续扩展而非撤销。", - "evidence": [ - "group helper将有效API key哈希写入auth_cache_invalidation_outbox,只输出sha256缓存键而非key原文。", - "账号UPDATE用IS NOT DISTINCT FROM逐项抑制无变化,BEFORE DELETE在membership还存在时枚举组;membership变更对旧/新组发失效。", - "刻意不把schedulable、临时限制、余额marker当身份字段;持久stop/schedule意图不由该迁移改变。", - "236重新定义相关function并扩展wire/profile、scheduler事件和拓扑同步,本文件仍是合法历史链节点。" - ] - }, - { - "path": "backend/migrations/213_codexrip_reset_unconfirmed_cindy_balance_markers.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "b0c9c93bd967984284bb6c3d2836747e96f78340ab044e549a39a1ca2bf419f8", - "review_fingerprint": "b0c9c93bd967984284bb6c3d2836747e96f78340ab044e549a39a1ca2bf419f8", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整15行;明确退役单个请求级预算信号推断永久耗尽的历史marker,不是当前启动时复测或自动恢复。", - "evidence": [ - "无logs条件,直接只对非NULL、严格旧OpenAI+Laxa API key marker置NULL;与210/211的证据恢复策略不同是有意后续政策。", - "保留status、schedulable、credentials、extra及其他provider;软删除账户的历史marker也清掉,不取消删除。", - "当前双控制模型/独立health episode由宿主另行管理,已应用后不会因新启动重清标记。" - ] - }, - { - "path": "backend/migrations/224_cindy_balance_probe_jobs.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "532461f5f4b6fe1b6f42c0d1a0e64d8b67561a308a94365044173b019cecf0ec", - "review_fingerprint": "532461f5f4b6fe1b6f42c0d1a0e64d8b67561a308a94365044173b019cecf0ec", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整65行;建立durable job/item账本的当前必要宿主机制,不包含创建或恢复任务的DML。", - "evidence": [ - "job状态明确保存queued/running/paused/paused_upstream/cancel_requested/terminal,活动唯一索引包括paused和cancel_requested,防止暂停任务被新任务覆盖。", - "item保存identity fingerprint、账号更新时间、was_marked、stage/outcome;request_count约束0..2,无credentials/token/raw请求响应列。", - "没有accounts FK的item保留账号删除后的历史;job外键cascade仅在明确删除job时生效;迁移本身不删job或改停止意图。", - "只读对照现有ClaimJob排除paused;Resume才从paused变queued;ReserveNext先计预留次数,不能把request_count解释为实际发送数。" - ] - }, - { - "path": "backend/migrations/229_cindy_platform_wire_identity.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "e64a9d64ef80da2de83e69c696b4df3023fe0e80247c14b71a3b95ac2ce06dcf", - "review_fingerprint": "e64a9d64ef80da2de83e69c696b4df3023fe0e80247c14b71a3b95ac2ce06dcf", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "276行历史SQL的既有全文审查复用同SHA。原missing-base_url使CHECK得到UNKNOWN及fallback负向NULL问题保持原字节作为历史;运行终态由252 NULL-total CHECK/discover取代。未记账且精确旧guard会失败的输入,由新runner只读检查在首写前拒绝并报告,不自动改账号或伪造迁移。关闭的是审查与已实施处置,不声明任意老库可无条件升级。", - "evidence": [ - "artifacts/evidence/v027-historical-migration-integration-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-implementation-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-design.json", - "artifacts/evidence/v027-astra-cindy-migration-history-review.json", - "artifacts/evidence/v027-astra-cindy-migration-remainder-review.json", - "artifacts/evidence/v027-astra-platform-quota-forward-union-review.json" - ] - }, - { - "path": "backend/migrations/230_account_credential_identities.sql", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "fc863aa1e69d57c618eb85538b2d1bc2d90566e745e763e7455bcd0e3c92d98e", - "review_fingerprint": "fc863aa1e69d57c618eb85538b2d1bc2d90566e745e763e7455bcd0e3c92d98e", - "review_status": "pending" - }, - { - "path": "backend/migrations/231_cindy_health_state.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "f8e69a148d0d37cef285a7415bfbe5c8dd2dbf7c4b06cf356c7107bc751e009d", - "review_fingerprint": "f8e69a148d0d37cef285a7415bfbe5c8dd2dbf7c4b06cf356c7107bc751e009d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整42行;当前health持久状态以credential identity/generation/episode绑定,不挟持管理员status/schedulable。", - "evidence": [ - "外键绑定accounts及account_credential_identities,generation>0、episode非空;quarantined/confirmed的quarantine_until和confirmed_at形状受CHECK约束。", - "只把现存非NULL严格canonical marker与active credential identity join成legacy-confirmed,不创造探测或改管理员调度。", - "ON CONFLICT(account_id) DO NOTHING保留已有episode;237后续扩展banned状态与账号generation投影。" - ] - }, - { - "path": "backend/migrations/232_admin_account_jobs.sql", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "fc0d4fda0ce5d8a9c070857417470dfda50500b267e2d125c94b5ee994bf8ba5", - "review_fingerprint": "fc0d4fda0ce5d8a9c070857417470dfda50500b267e2d125c94b5ee994bf8ba5", - "review_status": "pending" - }, - { - "path": "backend/migrations/233_image_studio_jobs.sql", - "candidate_owner": "image-tools", - "role": "source", - "present": true, - "content_sha256": "da44a7a739a09d16d5abf1d91a820c361445baead5dd8810e590c9cecfc99a6b", - "review_fingerprint": "da44a7a739a09d16d5abf1d91a820c361445baead5dd8810e590c9cecfc99a6b", - "review_status": "pending" - }, - { - "path": "backend/migrations/234_fix_cindy_platform_projection_round_trip.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "68dc70e69876d037a025410295e99509145ef9def6c118d3b948127db23b48f4", - "review_fingerprint": "68dc70e69876d037a025410295e99509145ef9def6c118d3b948127db23b48f4", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "227行历史234全文审查与同SHA复用。旧负向NULL成员判断由252 forward definition修正,不重放旧迁移、不清投影账本;仍pending234/235时读前检查先按实际ledger restore/to-legacy预览其guard,避免直接用当前平台误拒。已应用生产路径只定义新版行为,所有业务行保留。", - "evidence": [ - "artifacts/evidence/v027-historical-migration-integration-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-implementation-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-design.json", - "artifacts/evidence/v027-astra-cindy-migration-history-review.json", - "artifacts/evidence/v027-astra-cindy-migration-remainder-review.json", - "artifacts/evidence/v027-astra-platform-quota-forward-union-review.json" - ] - }, - { - "path": "backend/migrations/235_preserve_mixed_openai_cindy_groups.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "cb688ce57e663e86b300f18a3cc7921f281138a0a054eb32615ab6cd6468c170", - "review_fingerprint": "cb688ce57e663e86b300f18a3cc7921f281138a0a054eb32615ab6cd6468c170", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整61行;按当前拓扑修复234过宽ledger replay,同时保留回滚账本及手动membership,不能重放来替用户改分组。", - "evidence": [ - "文件先调用to_legacy,再重新定义from_legacy:先current discover,随后仅软删除且仍精确API-key/Laxa的账号可ledger replay。", - "组只在软删除或没有未删除成员时ledger replay;平台/wire/profile须与原ledger元组IS NOT DISTINCT FROM,保护后来管理员改变身份。", - "不insert/update/delete account_groups、不删除ledger;配套integration明确assert混合组仍OpenAI、独立纯组仍Cindy、生命周期排除对象可回放。", - "仍调用234的discover,因此相关NULL预检风险需在后续追加方案一并处理;本文件本身不被改写。" - ] - }, - { - "path": "backend/migrations/236_bind_strict_cindy_groups_to_catalog_channel.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "d66f3323ab56fefc8cf61a0f14fe1036bc46b1f919078f4876bfe50de9812218", - "review_fingerprint": "d66f3323ab56fefc8cf61a0f14fe1036bc46b1f919078f4876bfe50de9812218", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "542行历史236全文审查与同SHA复用。managed channel、映射/价格不可变及durable invalidation触发器维持原来源;旧NOT(strict-member)的UNKNOWN漏计由252替换同名strict函数解决。252在锁内重验现有canonical拓扑,有坏行拒绝而非自动解绑分组或换账号;旧文件不修改。", - "evidence": [ - "artifacts/evidence/v027-historical-migration-integration-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-implementation-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-design.json", - "artifacts/evidence/v027-astra-cindy-migration-history-review.json", - "artifacts/evidence/v027-astra-cindy-migration-remainder-review.json", - "artifacts/evidence/v027-astra-platform-quota-forward-union-review.json" - ] - }, - { - "path": "backend/migrations/237_add_minimax_platform.sql", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "5d6ef678851af723c253e88e4952c2c560eb25474c539fff0a3b1840c3b6b910", - "review_fingerprint": "5d6ef678851af723c253e88e4952c2c560eb25474c539fff0a3b1840c3b6b910", - "review_status": "pending" - }, - { - "path": "backend/migrations/237_cindy_terminal_health_and_cleanup.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "38101a38c688d078aecf522c2a3739a5a09ddb42168768edb5b76a3056bc15fd", - "review_fingerprint": "38101a38c688d078aecf522c2a3739a5a09ddb42168768edb5b76a3056bc15fd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整58行;扩展持久banned与generation投影,不是删除账号/备份或自动探测清理。", - "evidence": [ - "新增nullable banned_at、非负generation默认0;从active identity回填generation,INSERT/UPDATE active/generation触发投影。", - "active=false时仅在账号仍等于旧generation时归零,避免旧身份撤销覆盖替代generation;不改status/schedulable或凭据原文。", - "health状态CHECK扩展banned,终态confirmed_at非NULL/quarantine_until=NULL;保留quarantined形状与按generation CAS注释。" - ] - }, - { - "path": "backend/migrations/237_user_platform_quotas_add_cindy.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "1911eac4d84bbce7f627ea27232a55dc7e7ac40d5907a3a8aa20d9b0604a7c7a", - "review_fingerprint": "1911eac4d84bbce7f627ea27232a55dc7e7ac40d5907a3a8aa20d9b0604a7c7a", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整14行;已发布Cindy quota平台扩展必须原样保留,最终MiniMax/OpenCode兼容由后续文件负责。", - "evidence": [ - "只DROP/ADD固定user_platform_quotas_platform_check,把cindy加入当时既有平台集合;没有quota行DML、NULL清理或usage重算。", - "文件使用完整filename记账;与237_add_minimax等同数字前缀不同名可并存,但执行顺序是字典序,不能单独重放此较窄旧CHECK。", - "TrimSpace checksum 0e61f…匹配现有pinned test;该test明确禁止为MiniMax改写历史Cindy SQL或加checksum例外。", - "本批未阅读全文241;已存在v0.2.5历史只读证据显示当时最终constraint允许Cindy/MiniMax/OpenCode Go,不能将这个中间CHECK误当当前最终配置。" - ] - }, - { - "path": "backend/migrations/238_cindy_account_stats_reset_at.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "2c958be67436436dfdb07fc153296c9d4fe93291c08cfd629e2ede1d9f4d6897", - "review_fingerprint": "2c958be67436436dfdb07fc153296c9d4fe93291c08cfd629e2ede1d9f4d6897", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整12行;增加统计下界水位及dedup账号字段,不改历史usage、余额或quota NULL行。", - "evidence": [ - "cindy_account_stats_reset_at nullable列及partial index;usage_billing_dedup新增nullable account_id,旧行保持NULL而非伪造归属。", - "没有UPDATE/DELETE usage_logs或用户余额。后续读路径决定如何使用水位;本批不运行数据层测试。", - "runner归一化checksum 15c06d…与2026-09-15两份保存的生产QUOTA_V025_MIGRATION记录相同且present=true;这是该文件的历史应用证据,不是本轮实时DB核验。" - ] - }, - { - "path": "backend/migrations/238_opencode_go_platform.sql", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "82bade2e7dd4e6a6679770b0d4be9b5866ab7b6758870a7489db38c72bf512e9", - "review_fingerprint": "82bade2e7dd4e6a6679770b0d4be9b5866ab7b6758870a7489db38c72bf512e9", - "review_status": "pending" - }, - { - "path": "backend/migrations/239_codexrip_release_acceptance_api_key_leases.sql", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "990d813606931946439c10efab99886f25d3a7adb5789e1f92903b72f6176684", - "review_fingerprint": "990d813606931946439c10efab99886f25d3a7adb5789e1f92903b72f6176684", - "review_status": "pending" - }, - { - "path": "backend/migrations/240_admin_account_capabilities.sql", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "f12949c89b6449b33b17598a2294babc7ca92abf8440385278ece87695e54879", - "review_fingerprint": "f12949c89b6449b33b17598a2294babc7ca92abf8440385278ece87695e54879", - "review_status": "pending" - }, - { - "path": "backend/migrations/241_minimax_cindy_platform_quota_compat.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "93f46626268aa0e3b6a51b1635616b2cbe0e7e85f39be0d8f859f9e1c192b3cb", - "review_fingerprint": "93f46626268aa0e3b6a51b1635616b2cbe0e7e85f39be0d8f859f9e1c192b3cb", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "13行历史241全文审查及当前SHA确认。保留其旧十平台CHECK历史字节;最终允许集合由251恢复11平台。若241尚pending且存在其不支持、又不会被既定pending purge删除的行,首写前精确拒绝,真实PG已证明保留行/xmin/旧约束;不是仅靠尾部251假称能越过旧241失败。", - "evidence": [ - "artifacts/evidence/v027-historical-migration-integration-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-implementation-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-design.json", - "artifacts/evidence/v027-astra-cindy-migration-history-review.json", - "artifacts/evidence/v027-astra-cindy-migration-remainder-review.json", - "artifacts/evidence/v027-astra-platform-quota-forward-union-review.json" - ] - }, - { - "path": "backend/migrations/242_retire_public_model_manager.sql", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "3c9d2a7624896f0719c8d8f99c9e6db1c87a48f9c6fe7ef04529ee4d8c406889", - "review_fingerprint": "3c9d2a7624896f0719c8d8f99c9e6db1c87a48f9c6fe7ef04529ee4d8c406889", - "review_status": "pending" - }, - { - "path": "backend/migrations/243_codex_fingerprint_device_default.sql", - "candidate_owner": "core-data-and-migrations", - "role": "source", - "present": true, - "content_sha256": "917e7a14e967c3bac61bc7fa36f877fc70604b1b85bd4dd0396fad8bdba75692", - "review_fingerprint": "917e7a14e967c3bac61bc7fa36f877fc70604b1b85bd4dd0396fad8bdba75692", - "review_status": "pending" - }, - { - "path": "backend/migrations/244_codex_ticket_lifecycle.sql", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "3077f2469e54f22e4b51adeffd5cf82decb9967701aae5f9bf332a5522e1e6e4", - "review_fingerprint": "3077f2469e54f22e4b51adeffd5cf82decb9967701aae5f9bf332a5522e1e6e4", - "review_status": "pending" - }, - { - "path": "backend/migrations/245_codex_ticket_account_status_independent.sql", - "candidate_owner": "codex-runtime", - "role": "source", - "present": true, - "content_sha256": "f62046ccac1019486b02ed7d48dded4a02f45b8fc6fcbc5ffcee2961823775ad", - "review_fingerprint": "f62046ccac1019486b02ed7d48dded4a02f45b8fc6fcbc5ffcee2961823775ad", - "review_status": "pending" - }, - { - "path": "backend/migrations/246_plugin_extension_state.sql", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "30186f02799048b584259095d470e55df7bb5aa8d7ff7063e7a9e9d07642772d", - "review_fingerprint": "30186f02799048b584259095d470e55df7bb5aa8d7ff7063e7a9e9d07642772d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Limits database-exclusive enabled scopes to transport/provider capabilities and creates namespaced state and monotonically generated leases. State and lease rows deliberately have no installation FK and survive plugin uninstall.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Source inspection is not represented as an executed test." - ] - }, - { - "path": "backend/migrations/247_account_quota_estimates.sql", - "candidate_owner": "core-quota-and-protocol", - "role": "source", - "present": true, - "content_sha256": "38c6e5177fac0a598ea8cc9a750a47eb9331003e787544499dd8a9d4921e4f61", - "review_fingerprint": "38c6e5177fac0a598ea8cc9a750a47eb9331003e787544499dd8a9d4921e4f61", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-quota-and-protocol", - "reason": "Migration creates the account/identity/period primary key and stores reset, baseline, latest observation, and account-cost fields with an expiry index; schema supports the repository upsert contract.", - "evidence": [ - "coverage_role=core-quota-and-protocol; coverage_sha256=38c6e5177fac0a598ea8cc9a750a47eb9331003e787544499dd8a9d4921e4f61; current_sha256=38c6e5177fac0a598ea8cc9a750a47eb9331003e787544499dd8a9d4921e4f61; inventory_sha256_match=true", - "lines 1-14: table columns, composite primary key, and reset index", - "paired source: backend/internal/repository/account_quota_estimate.go:18-40" - ] - }, - { - "path": "backend/migrations/248_plugin_bundle_bootstrap.sql", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "2581aa2f9829c844ed75dba4d10de0dec4b9f4b12e72ae1d2143f3806ef8217b", - "review_fingerprint": "2581aa2f9829c844ed75dba4d10de0dec4b9f4b12e72ae1d2143f3806ef8217b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Creates the persistent completed/state_imported/user_removed bootstrap journal and desired-enabled intent, keyed by plugin identity without an installation FK, so update/delete does not erase one-time migration history.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Source inspection is not represented as an executed test." - ] - }, - { - "path": "backend/migrations/249_plugin_bundle_binding_intent.sql", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0ab3745dca07ecacd72a8b70597e5c2e8cb2918c7854d4a9c19371bb8a49c602", - "review_fingerprint": "0ab3745dca07ecacd72a8b70597e5c2e8cb2918c7854d4a9c19371bb8a49c602", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Adds nullable array-validated desired_bindings for resuming a staged bootstrap without learning temporary disabled rows as administrator intent. Existing completed installations are not rewritten.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Source inspection is not represented as an executed test." - ] - }, - { - "path": "backend/migrations/250_plugin_independent_updates.sql", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "0bc14303185d14a8ef3d06103a6a432f52eca22bf6fa41edf1526c817a35703a", - "review_fingerprint": "0bc14303185d14a8ef3d06103a6a432f52eca22bf6fa41edf1526c817a35703a", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Adds updating state, revision/runtime generation, immutable package digest and pinned/bundled policy; backfills stored package digests and bundled policy. Pending updates reference only the target installation. The revision trigger increments on config/state/policy/generation/manifest changes or explicit binding revision, not repeated health timestamp publication.", - "evidence": [ - "artifacts/evidence/v027-astra-update-persistence-review.json: per-file full-read conclusions, traced SQL/call flow, targeted command RUN/PASS and explicit non-execution limits", - "Source inspection is not represented as an executed test." - ] - }, - { - "path": "backend/migrations/251_user_platform_quota_platform_union.sql", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "3390de91ebe0b508010509e2b2054ac0bc0705a0e739b9d13ca29b22ccfcdb0b", - "review_fingerprint": "3390de91ebe0b508010509e2b2054ac0bc0705a0e739b9d13ca29b22ccfcdb0b", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-extension-and-job-host", - "reason": "新12行forward-only migration,唯一生产改动是重建user_platform_quotas_platform_check为当前完整11平台并集。历史238/241原始字节和checksum完全保留,不删除/重写quota行。", - "evidence": [ - "先确认当前最大迁移250且无251文件,再新增251_user_platform_quota_platform_union.sql;没有占用其它代理编号。", - "DROP IF EXISTS和ADD同名CHECK;允许集合=原241十项+opencode_go。无DML、无未知平台通配、无SQL NULL账号身份修复。", - "注释直接保留兼容边界:尾部251不能越过未记账241在existing Go rows上的早期校验失败。", - "证据:artifacts/evidence/v027-astra-platform-quota-forward-union-review.json;真实PG targeted test已经执行通过,不声称旧全库迁移链通过。" - ] - }, - { - "path": "backend/migrations/252_cindy_identity_null_total.sql", - "candidate_owner": "cindy-provider", - "role": "source", - "present": true, - "content_sha256": "4c24778c9f63b568db9976e7fddd96675e52c5871533b0fc8071f6a25028f080", - "review_fingerprint": "4c24778c9f63b568db9976e7fddd96675e52c5871533b0fc8071f6a25028f080", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-data-and-migrations", - "reason": "完整297行前向迁移及原函数差分核对。runner事务内5s/60s锁与语句上限,锁accounts/groups/membership后先重验,账户CHECK整体IS TRUE、strict成员反向条件IS NOT TRUE、旧discovery七处IS DISTINCT FROM。不调用投影函数、不更新业务行;坏数据整个252失败,旧约束/函数保留。不是改历史checksum,也不把NOT VALID当成不影响旧行的捷径。", - "evidence": [ - "artifacts/evidence/v027-historical-migration-integration-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-implementation-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-design.json" - ] - }, - { - "path": "backend/migrations/account_credential_identity_migration_test.go", - "candidate_owner": "core-data-and-migrations", - "role": "test-or-fixture", - "present": true, - "content_sha256": "db45bdd57e4a8c272a475f2f20e9f73bf594d5d26848396ecbcab184419f3a70", - "review_fingerprint": "db45bdd57e4a8c272a475f2f20e9f73bf594d5d26848396ecbcab184419f3a70", - "review_status": "pending" - }, - { - "path": "backend/migrations/account_jobs_slim_migration_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "ee23fcb9525b9e22f9da4108c11001a61bbb188c635df430b283c367d9390fea", - "review_fingerprint": "ee23fcb9525b9e22f9da4108c11001a61bbb188c635df430b283c367d9390fea", - "review_status": "pending" - }, - { - "path": "backend/migrations/business_system_prompt_codex_skill_hybrid_migration_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "cb61b6155c81b6befaf2f7dd49be1737fdd7d967bd55c762c445a1a7f4ec595c", - "review_fingerprint": "cb61b6155c81b6befaf2f7dd49be1737fdd7d967bd55c762c445a1a7f4ec595c", - "review_status": "pending" - }, - { - "path": "backend/migrations/business_system_prompt_managed_source_migration_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "0bfbe349bbcfe3697717e20e1fd9fa89924cca6ba72bd5db25dc9d6c9a08e8ff", - "review_fingerprint": "0bfbe349bbcfe3697717e20e1fd9fa89924cca6ba72bd5db25dc9d6c9a08e8ff", - "review_status": "pending" - }, - { - "path": "backend/migrations/business_system_prompt_remote_skill_migration_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "21397d73f2efad015fbf1de18f6e9494ddf071a3defacb6601274aef0d80634a", - "review_fingerprint": "21397d73f2efad015fbf1de18f6e9494ddf071a3defacb6601274aef0d80634a", - "review_status": "pending" - }, - { - "path": "backend/migrations/business_system_prompt_skill_bundles_migration_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "81c9195a4a16a1f742f8830fb43a23c338ae9bccf90f0ea90e5e452798847266", - "review_fingerprint": "81c9195a4a16a1f742f8830fb43a23c338ae9bccf90f0ea90e5e452798847266", - "review_status": "pending" - }, - { - "path": "backend/migrations/business_system_prompts_migration_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "308ccb859bdbd9d6fbd58a245ef2d81a330c808718fe9176d00ef9cd59a24b35", - "review_fingerprint": "308ccb859bdbd9d6fbd58a245ef2d81a330c808718fe9176d00ef9cd59a24b35", - "review_status": "pending" - }, - { - "path": "backend/migrations/cindy_account_stats_reset_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "27e3f9dd05c977624bb1c411d7f483c247fec081da038b61b5aed7de77ee0a9e", - "review_fingerprint": "27e3f9dd05c977624bb1c411d7f483c247fec081da038b61b5aed7de77ee0a9e", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整20行;四个Contains断言只检查迁移含两个表和新增字段,不能证明运行时统计或历史数据不变。", - "evidence": [ - "使用embedded FS读取完整filename;lowercase后检查watermark/accounts/dedup/account_id。", - "本轮未执行;未把测试名Adds...当SQL实际已成功应用或数据行为覆盖。" - ] - }, - { - "path": "backend/migrations/cindy_alpha_search_bridge_migration_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "91f3b02d3f99afd1fb00bdeb83418d138642d33974c477e4d3f10facb26830a7", - "review_fingerprint": "91f3b02d3f99afd1fb00bdeb83418d138642d33974c477e4d3f10facb26830a7", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整93行;逐项读完209的合成schema/样例和结果断言,明确是历史桥接字段迁移fixture而非当前搜索功能验证。本轮未执行测试。", - "evidence": [ - "CREATE accounts包含credentials/extra非NULL JSON、status、deleted_at;active样例实际status=disabled,带force_responses、旧direct search、既有sha256_64和ordinary键。", - "执行209后要求只把search改responses_web_search;完整Extra JSONEq保留Responses模式、prompt hash及ordinary键,Credentials JSONEq原样保留,status仍disabled、deleted=false。", - "soft-deleted error账号同样只改search,保留ordinary布尔、error status及deleted=true;普通OpenAI、Laxa /v1路径和OAuth三类样例Extra保持原值。", - "already-bridge样例以xmin RowVersion断言首次迁移不写;active再次执行后xmin和Extra不变。共享readCindyMigrationAccount helper在本批defaults integration文件中全文读到。", - "只有209独立执行的设定;207先给direct、209后改bridge的历史演进不是本轮运行证据。未把函数名StrictAndIdempotent当作已测试通过。", - "证据:artifacts/evidence/v027-astra-cindy-migration-remainder-review.json;本轮未执行任何测试或SQL。" - ] - }, - { - "path": "backend/migrations/cindy_alpha_search_bridge_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6ce2489d65e112bf4fab7d17c8eaf51a274a956c31eab84a786af5e3265c5f68", - "review_fingerprint": "6ce2489d65e112bf4fab7d17c8eaf51a274a956c31eab84a786af5e3265c5f68", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整28行;精确检查209仅写search模式并保留其他字段,不是搜索provider联调证明。", - "evidence": [ - "断言jsonb_set、responses_web_search、严格platform/type/root URL与IS DISTINCT FROM;反向断言不含prompt/responses键、credentials/updated_at改写。", - "明确不要求deleted_at IS NULL,保留旧政策包含软删除严格身份的事实;对应integration留下一批。" - ] - }, - { - "path": "backend/migrations/cindy_balance_confirmation_reset_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "5475c1b4da2e18408663b87a401ba3f1930d914439b5a5e22d1051fe6c66b93a", - "review_fingerprint": "5475c1b4da2e18408663b87a401ba3f1930d914439b5a5e22d1051fe6c66b93a", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整30行;只核对213的严格marker reset文本以及禁止改status/schedulable等字段。", - "evidence": [ - "要求marker非NULL/strict old identity/exact root;不含logs依赖和deleted_at过滤。", - "只静态阅读,未以该断言宣称所有NULL数据集或数据库执行通过。" - ] - }, - { - "path": "backend/migrations/cindy_balance_marker_reset_migration_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "13c8ceeb8f69ab1b15a0edefca6d87db5aac8f2b3d7ed8acbc66b261022321da", - "review_fingerprint": "13c8ceeb8f69ab1b15a0edefca6d87db5aac8f2b3d7ed8acbc66b261022321da", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整315行,逐个读三份合成schema/数据和SQL执行后断言;本轮不连数据库、不执行。", - "evidence": [ - "210场景:缺code预算事件被清,精确type/code旧deleted标记保留;普通provider/path/oauth保留;status/schedulable/credentials/extra/xmin断言。", - "211场景:exact unresolved恢复到事件时间;numeric code、message-only、402、deleted/ordinary和later usage不恢复;已有marker及重复应用xmin保持。", - "213场景:active/deleted strict旧identity marker清除,ordinary/path/oauth和unmarked xmin保持,重复应用无新增改动。", - "read snapshot将对象字段与xmin读回;fixture只覆盖这些样例,不包含229/236缺失base_url的三值逻辑断言。" - ] - }, - { - "path": "backend/migrations/cindy_balance_marker_reset_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "70167600b9df4e4dcf76872bd7b8924e2bad4fddc2ed508e27f9bd21ed29a19a", - "review_fingerprint": "70167600b9df4e4dcf76872bd7b8924e2bad4fddc2ed508e27f9bd21ed29a19a", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整44行;锁定210 TrimSpace hash并核对指定清理谓词,不能把内容固定等同全部业务语义正确。", - "evidence": [ - "pinned checksum ec98aa…;required exact structured columns/status429/2minute窗口;forbid宽泛ExceededBudget字符串、status/schedulable/cred修改。", - "本轮只复算文件hash以核对历史身份,未运行Go测试或旧SQL。" - ] - }, - { - "path": "backend/migrations/cindy_balance_marker_restore_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b70d248a4cf29e9d94a74b2b5196d00ae27a07b1fcf825a0651c973d53a6c227", - "review_fingerprint": "b70d248a4cf29e9d94a74b2b5196d00ae27a07b1fcf825a0651c973d53a6c227", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整35行;检查211从已消毒JSON精确类型恢复的合同,未运行。", - "evidence": [ - "要求IS JSON、type/code字符串类型、最新后无usage条件与marker原为NULL;拒绝使用provider_error列/宽泛message及其他账号字段赋值。", - "此fixture表达211阶段合同,不替代213后续退役单信号mark的最终政策。" - ] - }, - { - "path": "backend/migrations/cindy_balance_probe_jobs_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "fff48f958ed70abce99daf7790dd8fcb9def4cf69157d4df0ea30ec554faae26", - "review_fingerprint": "fff48f958ed70abce99daf7790dd8fcb9def4cf69157d4df0ea30ec554faae26", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整72行;四个具体文本断言组核对filename、表/唯一键、活动状态、速率/计数以及不存秘密;没有实际job恢复测试。", - "evidence": [ - "允许多个224_*.sql但要求完整filename存在;唯一active索引显式包含paused/paused_upstream/cancel_requested。", - "item计数0..2和job非负计数、hash字段/outcome列得到Contains检查;forbid api_key/access_token/credentials/request/response/raw_error等列文本。", - "这些检查不证明worker遵守stop intent;本轮另只读对照ClaimJob/Resume/RecoverInterruptedItems调用处,不重跑历史服务测试。" - ] - }, - { - "path": "backend/migrations/cindy_channel_binding_migration_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6fbedd6ecad8f907cc42f06cfff2a39357d2a08f8b50cc34600794e8c23be007", - "review_fingerprint": "6fbedd6ecad8f907cc42f06cfff2a39357d2a08f8b50cc34600794e8c23be007", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整221行;四个场景和完整fixture schema逐项审阅,未执行。", - "evidence": [ - "对strict/mixed组应用236两次,要求marker唯一、strict一个binding、mixed无binding、price表空、scheduler/auth outbox各一条。", - "strict组已有operator channel及marker带custom data均要求RAISE;不自动偷走或覆盖绑定。", - "从空canonical组加入合法账号获得binding;加入ordinary、fallback_on_invalid、换profile被拒;移走最后成员后解绑。", - "fixture包含全部auth trigger引用的group字段,避免假字段缺失;没有缺失base_url canonical成员案例,所以未覆盖F-identity-null-check。" - ] - }, - { - "path": "backend/migrations/cindy_group_identity_auth_cache_invalidation_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "1c7b18eb79752d3f4b392cfe9f59999fe30be451fae199f4fec6ffb44ffd3c0b", - "review_fingerprint": "1c7b18eb79752d3f4b392cfe9f59999fe30be451fae199f4fec6ffb44ffd3c0b", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整26行;只核对212的trigger timing和字段选择,未运行。", - "evidence": [ - "要求account UPDATE/BEFORE DELETE与membership INSERT/UPDATE/DELETE、old/new identity去重和SHA256 key outbox。", - "反向断言不含schedulable/temp_unschedulable/balance marker,保护运行态变化不冒充身份变更。" - ] - }, - { - "path": "backend/migrations/cindy_health_state_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f91f3b8d2d03a17f5198300f0b79e825fa152ec799d7602c9285ca08b5699bc6", - "review_fingerprint": "f91f3b8d2d03a17f5198300f0b79e825fa152ec799d7602c9285ca08b5699bc6", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整41行;两项Contains/NotContains合同分别针对231和237,不是health动态CAS执行证据。", - "evidence": [ - "231要求generation/episode/identity FK和confirmed_exhausted,排除旧复杂receipt/probe_lease等结构;237要求banned_at/generation同步trigger和扩展状态枚举。", - "未检验实际credential替换/并发episode写入,本轮亦未运行这些业务测试。" - ] - }, - { - "path": "backend/migrations/cindy_openai_defaults_migration_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "785498e88aa4fb508873c2462ce243bb0ca3e2877e7a7bc088dc48be5d779b0b", - "review_fingerprint": "785498e88aa4fb508873c2462ce243bb0ca3e2877e7a7bc088dc48be5d779b0b", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整136行;207默认值恢复的七类样例、字段保留与xmin重复执行断言逐项审阅,且完整读取本批三个integration共享的快照helper。本轮未执行测试。", - "evidence": [ - "严格旧OpenAI+Laxa API key的混合大小写/空格/末尾slash样例:仅search改direct、prompt-cache改passthrough;force_responses、ordinary键、credentials、disabled状态和未删除标志保留。", - "soft-deleted error样例添加两个默认键但不恢复删除或status;uppercase scheme样例按SQL lower/btrim规则也迁移。", - "ordinary OpenAI、Laxa /v1、Laxa query URL、Laxa OAuth四组被JSONEq断言完整保留旧Extra值,避免宽松域名包含匹配。", - "第二次执行207比较active xmin和Extra,验证fixture想表达无变化不写。helper以参数化name查询credentials/extra/status/deleted/xmin,不拼接输入SQL。", - "207的direct/passthrough是历史阶段;208后来独立改prompt hash,209后来独立改search bridge,不能拿旧fixture默认值覆盖当前管理员选择。", - "证据:artifacts/evidence/v027-astra-cindy-migration-remainder-review.json;本轮未执行任何测试或SQL。" - ] - }, - { - "path": "backend/migrations/cindy_openai_defaults_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "abe229c93dc218ab747944c5037dbb4450566a2af54b64841f2798185a4e1387", - "review_fingerprint": "abe229c93dc218ab747944c5037dbb4450566a2af54b64841f2798185a4e1387", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整30行;静态字符串合同明确绑定207的两个Extra键和strict旧身份条件,不是SQL数据级执行测试。本轮未运行。", - "evidence": [ - "要求embedded FS完整文件名、UPDATE accounts/jsonb_set、alpha_search direct与prompt_cache passthrough两个写值。", - "断言platform=openai、type=apikey、lower/btrim base_url与末尾slash精确字面量,且两字段都有IS DISTINCT FROM。", - "反向断言不出现deleted_at IS NULL、SET credentials或updated_at赋值,表达软删除身份也纳入旧迁移、凭据不改的既有契约。", - "仅查文本存在/不存在,没有SQL执行、row count或完整predicate truth-table;应与已审阅207源码及对应integration意图合看。", - "证据:artifacts/evidence/v027-astra-cindy-migration-remainder-review.json;本轮未执行任何测试或SQL。" - ] - }, - { - "path": "backend/migrations/cindy_platform_v1_migration_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "52efe08298aabffff40691b844026e5af5e11f4c9c269f8827aea6f40dee7654", - "review_fingerprint": "52efe08298aabffff40691b844026e5af5e11f4c9c269f8827aea6f40dee7654", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整400行;229→234→235的三条真实fixture链与所有身份/ledger/idempotence断言已阅读,本轮未执行。", - "evidence": [ - "229只投影活动严格组;soft-deleted ordinary companion原先阻止strict同伴,234后忽略已删除成员并恢复空组/软删除ledger、可rollback/forward。", - "第二场景先rollback再加ordinary成员,234故意复现混合组错误推广;235后混合组及账号保留OpenAI,独立纯组Cindy、ledger不删除、二次forward计数0。", - "第三场景对soft-deleted ledger账号改auth type、URL指向或URL数字类型后235不得回放,仍精确Laxa的软删账号可回放。", - "table参数先require在accounts/groups白名单再fmt SQL,name值参数化;fixture没有缺键base_url或canonical CHECK UNKNOWN场景。" - ] - }, - { - "path": "backend/migrations/cindy_platform_v1_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "821e990b0d64c427ca187498ddcf54fa8db6af32b32687d703bdc930d3800224", - "review_fingerprint": "821e990b0d64c427ca187498ddcf54fa8db6af32b32687d703bdc930d3800224", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整231行;八个测试的内容比较/顺序/字段检查全部阅读,未运行。", - "evidence": [ - "229断言精确URL/ledger/双向function且无trigger/模糊host匹配;235_group_model_allowlist的rename-only expected文本保留JSON原值,虽然该SQL不在本批全文审阅集。", - "235混合组修复按BEGIN→to_legacy→redefine→from_legacy→COMMIT顺序,禁止改membership/删ledger;同时只读取workflow寻找必需测试名,这不等于本轮CI通过。", - "236检查两份同前缀完整filename、超时/锁、marker、两个fallback、durable outbox/trigger及禁止硬编码模型/价格;另核对完整group auth字段、trim reserved names和integration fixture列集。", - "这些是文本约束,不能推导CHECK遇UNKNOWN或所有SQL数据形状已被实际测试。" - ] - }, - { - "path": "backend/migrations/cindy_prompt_cache_hash_migration_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "15c2de669fbd370b70128bdf0f6fb35127f59fb157853181b13ac1968fcd9fec", - "review_fingerprint": "15c2de669fbd370b70128bdf0f6fb35127f59fb157853181b13ac1968fcd9fec", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整94行;208只迁移prompt-cache模式的合成数据与具体不变断言全文审阅,未执行。", - "evidence": [ - "active严格根URL样例的passthrough改sha256_64,同时保留force_responses、direct search、ordinary键、原credentials、disabled状态及deleted=false。", - "soft-deleted error样例只加hash模式,仍error/deleted;ordinary OpenAI、Laxa /v1路径及OAuth三类Extra JSON保留。", - "already-hashed样例首次执行前后xmin相同;active第二次执行后xmin和Extra相同。共享helper的查询字段与参数化输入已读。", - "该fixture证明意图是207之后只替换prompt字段、不重写search;209后续搜索切换与本字段独立。", - "证据:artifacts/evidence/v027-astra-cindy-migration-remainder-review.json;本轮未执行任何测试或SQL。" - ] - }, - { - "path": "backend/migrations/cindy_prompt_cache_hash_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "9232f28dc09a9fa49ed00d2f712879bf3d08048fa703e52388936961126be92a", - "review_fingerprint": "9232f28dc09a9fa49ed00d2f712879bf3d08048fa703e52388936961126be92a", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整28行;208静态合同要求唯一prompt key写入和strict旧Cindy识别,明确排除另外两种OpenAI模式。本轮未运行。", - "evidence": [ - "要求jsonb_set与sha256_64、platform/type、lower/btrim URL及IS DISTINCT FROM。", - "不含alpha_search_mode/responses_mode写入、不含deleted_at IS NULL、SET credentials或updated_at赋值。", - "这是SQL文本约束而非运行结果;不能推导网络模型、真实prompt cache复用或所有历史迁移组合通过。", - "证据:artifacts/evidence/v027-astra-cindy-migration-remainder-review.json;本轮未执行任何测试或SQL。" - ] - }, - { - "path": "backend/migrations/historical_cindy_null_total_migration_integration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8226c6899d33048ac32c86dd7ed10227324537e4c7618a144149db8dce015fc4", - "review_fingerprint": "8226c6899d33048ac32c86dd7ed10227324537e4c7618a144149db8dce015fc4", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-data-and-migrations", - "reason": "完整344行真实PostgreSQL合成fixture阅读。正常252比较完整行/xmin与validated约束;真实fallback guard保留、NULL新写拒绝、隔离事务drop CHECK仅用于反证strict谓词后rollback;脏账号/组252失败保持schema,8类runner拒绝无账本/Atlas/prefix写,safe populated/recorded/缺列/restore共17场景按目标分批通过。仅专有库/schema,不在产品代码伪造账本。", - "evidence": [ - "artifacts/evidence/v027-historical-migration-integration-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-implementation-review.json", - "artifacts/evidence/v027-astra-historical-migration-compat-design.json" - ] - }, - { - "path": "backend/migrations/image_studio_jobs_migration_test.go", - "candidate_owner": "image-tools", - "role": "test-or-fixture", - "present": true, - "content_sha256": "8572b36e8217447dabb4ad08cde6235c0c29e009d9de53004e304750026f64e4", - "review_fingerprint": "8572b36e8217447dabb4ad08cde6235c0c29e009d9de53004e304750026f64e4", - "review_status": "pending" - }, - { - "path": "backend/migrations/minimax_platform_migration_test.go", - "candidate_owner": "core-data-and-migrations", - "role": "test-or-fixture", - "present": true, - "content_sha256": "f29f4e4021b5af67dbf29940153031d25d729718c62c125ed144c00dd63fafba", - "review_fingerprint": "f29f4e4021b5af67dbf29940153031d25d729718c62c125ed144c00dd63fafba", - "review_status": "pending" - }, - { - "path": "backend/migrations/opencode_go_platform_migration_test.go", - "candidate_owner": "core-data-and-migrations", - "role": "test-or-fixture", - "present": true, - "content_sha256": "4ae609a0a27f27058e9ea06c817eb49dd588dc372cc7c8665fcc40d900dbebec", - "review_fingerprint": "4ae609a0a27f27058e9ea06c817eb49dd588dc372cc7c8665fcc40d900dbebec", - "review_status": "pending" - }, - { - "path": "backend/migrations/platform_quota_forward_union_migration_integration_test.go", - "candidate_owner": "mixed-requires-review", - "role": "test-or-fixture", - "present": true, - "content_sha256": "707ee7228d0fcf69cba088c7fdff8827aed69e7f036ad827d370dc1c4f8b1d44", - "review_fingerprint": "707ee7228d0fcf69cba088c7fdff8827aed69e7f036ad827d370dc1c4f8b1d44", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "新112行integration fixture在私有真实PostgreSQL schema中仅执行相关238/241/251;完整检查旧终态拒Go、新并集11平台、unknown拒绝、row/xmin保留、二次应用及已允许11的平台不收窄。", - "evidence": [ - "fresh_238_then_241子例实际应用原238/241并尝试Go写入,require PostgreSQL SQLSTATE23514且ConstraintName正确,直接证明旧终态回退而非只查schema字符串。", - "251前后完整to_jsonb(row)+xmin快照相同,覆盖ID/user/platform、NULL与0限额、usage、窗口、created/updated/deleted时间和软删除行。", - "每个11平台都真实INSERT成功,unknown两次被精确同名CHECK拒绝;再应用251后完整行/xmin不变。", - "already_all_eleven_platforms子例先用原238形成11平台schema并预置有效opencode_go quota行;251仍接受全部11且数据不变。", - "只用最小quota表及原238所需3个空依赖表,不运行整库migration runner;没有远程模型/真实业务数据。", - "证据:artifacts/evidence/v027-astra-platform-quota-forward-union-review.json。" - ] - }, - { - "path": "backend/migrations/release_acceptance_api_key_lease_migration_test.go", - "candidate_owner": "core-data-and-migrations", - "role": "test-or-fixture", - "present": true, - "content_sha256": "2afa0eb5fdd5628af9bbc3ab78acc6549b63c136f4978675adf69f1744cbc2ea", - "review_fingerprint": "2afa0eb5fdd5628af9bbc3ab78acc6549b63c136f4978675adf69f1744cbc2ea", - "review_status": "pending" - }, - { - "path": "backend/migrations/remote_skill_registry_migration_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "6a5df542f397a2a755a98c43dfcdb0ffe373dd826481b51aad9acf24546988d3", - "review_fingerprint": "6a5df542f397a2a755a98c43dfcdb0ffe373dd826481b51aad9acf24546988d3", - "review_status": "pending" - }, - { - "path": "backend/migrations/remote_skill_sources_migration_integration_test.go", - "candidate_owner": "prompt-skills", - "role": "test-or-fixture", - "present": true, - "content_sha256": "059a6ed960d9b45ccdbeab675e7f7b83e815bdd844d947b0cae58bdb90f887a6", - "review_fingerprint": "059a6ed960d9b45ccdbeab675e7f7b83e815bdd844d947b0cae58bdb90f887a6", - "review_status": "pending" - }, - { - "path": "backend/migrations/user_platform_quota_cindy_migration_test.go", - "candidate_owner": "cindy-provider", - "role": "test-or-fixture", - "present": true, - "content_sha256": "94322c5cba4ad229e30283aca4cf30c0c685326b36e1f6805cae72e0fd121b82", - "review_fingerprint": "94322c5cba4ad229e30283aca4cf30c0c685326b36e1f6805cae72e0fd121b82", - "review_status": "reviewed", - "decision": "reference", - "owner": "cindy-provider", - "reason": "完整25行;锁定已发布237 Cindy约束的内容和hash,防止把新平台兼容写回旧文件。", - "evidence": [ - "TrimSpace SHA256固定0e61f…并核对DROP/ADD及既定平台列表;本轮计算得到相同hash但没有运行Go测试。", - "注释明确MiniMax兼容属于后续237/241,不给历史迁移开checksum例外;并不测试全NULL quota行清理或最终全部平台并集。" - ] - }, - { - "path": "backend/pkg/extensionapi/proxy/address.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "f06c43cf4377f14b4e272405429940cd380daed4127eed5d58c86e5954224277", - "review_fingerprint": "f06c43cf4377f14b4e272405429940cd380daed4127eed5d58c86e5954224277", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全读纯proxy归一器:16KiB输入界限,URL/四段式/具名多行格式,标签别名与重复/缺字段拒绝,userinfo由net/url编码;只接受http/https/socks5/socks5h、显式1..65535端口和无path/query/fragment形式。错误不回显输入账密,无DNS/网络访问。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/proxy/transport.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "7be544d2b44e9b1b105b067f4fcafae7f5f816c7eb1b4fac8bea9da3149d9b65", - "review_fingerprint": "7be544d2b44e9b1b105b067f4fcafae7f5f816c7eb1b4fac8bea9da3149d9b65", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全读通用transport设置:nil transport拒绝,HTTP系使用标准ProxyURL;SOCKS使用有超时的dialer且必须支持ContextDialer,清Proxy后设置可取消DialContext。当前唯一调用在ticketProxyTransport中新建transport;不把此函数说成通用热重配/证书校验器。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/account-create.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "8ca0adf104b0a89ecb20af6a059bb1c48849772e34d8cdbd91a683041ad29f65", - "review_fingerprint": "8ca0adf104b0a89ecb20af6a059bb1c48849772e34d8cdbd91a683041ad29f65", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文核对TS与Go公开合同:固定Cindy/API-key/profile、五默认目标、三Responses枚举、只读端点提示、有限device identity绑定;请求只传版本前置条件和命名输入,不传私有表单或账号凭据。null load_factor有独立语义;minimum_effective_groups注释明确在host默认组回退后计算。", - "evidence": [ - "artifacts/evidence/v027-account-create-integration-review.json#verification", - "artifacts/evidence/v027-astra-account-create-frontend-review.json" - ] - }, - { - "path": "backend/pkg/extensionapi/ui/account-edit.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "a8431f25b5ce8bfde3dff7b7ea777ff0187c7646546ee5c43de1b49637b61f5c", - "review_fingerprint": "a8431f25b5ce8bfde3dff7b7ea777ff0187c7646546ee5c43de1b49637b61f5c", - "review_status": "pending" - }, - { - "path": "backend/pkg/extensionapi/ui/account-view.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "e341488108525b3c25bfc63df69ee6d7b79db892f4f9623910917ad1ddb743b9", - "review_fingerprint": "e341488108525b3c25bfc63df69ee6d7b79db892f4f9623910917ad1ddb743b9", - "review_status": "pending" - }, - { - "path": "backend/pkg/extensionapi/ui/base.css", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "56e8f3eefce7a74d79382955b05d019e9242ccce6269ba96dc670ca012d36ccc", - "review_fingerprint": "56e8f3eefce7a74d79382955b05d019e9242ccce6269ba96dc670ca012d36ccc", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整读812行通用按钮/输入/面板/表格/弹窗/导航/通知/状态/代码块/安全区域样式。保留原通用品牌支付按钮色,不加入支付逻辑;表格统一语义颜色、弹窗responsive高度/宽度/滚动锁和reduced-motion不依赖观测插件。只import本地theme.css,无远程资源或业务事件。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/bridge.js", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "0f884d679b4eb9fe70b52252aff5f8a980cce24f56ef15d91907ffcde0d4734e", - "review_fingerprint": "0f884d679b4eb9fe70b52252aff5f8a980cce24f56ef15d91907ffcde0d4734e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全读真实UI桥:校验parent来源窗口/短令牌/消息source,以request_id关联响应;具名资源和事件通过宿主,信号取消/页面释放清理pending。修复30秒timeout漏移除AbortSignal监听器,错误/成功/既有cancel协议均不改。无新网络权限;opaque iframe使用*发送目标而接收端有窗口和token检查。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Timeout listener regression executed against the actual SDK source with synthetic signals and timers." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/build.mjs", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "461eb892d268d26829da1a4bd63e214eb0654535865fb8a4ce727e34fe0547ea", - "review_fingerprint": "461eb892d268d26829da1a4bd63e214eb0654535865fb8a4ce727e34fe0547ea", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "从同一 inventory 选择 domain,校验目录,使用冻结 frontend 依赖;禁用外部 Vite config,阻止私有 host frontend/backend imports,仅构建插件源与公共 SDK。正式包使用 signer 前生成的这些资产。", - "evidence": [ - "selected domain guard", - "configFile:false", - "public-plugin-source-boundary resolve/load hooks", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/client.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "5c92394724dd04c4de61d2d0f7ca628d5a2c1f3de464800bec8e99e187b4b9f3", - "review_fingerprint": "5c92394724dd04c4de61d2d0f7ca628d5a2c1f3de464800bec8e99e187b4b9f3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Full-file review and additive SDK change: resourceAvailability is a read-only named availability query, not an arbitrary URL or authorization engine.", - "evidence": [ - "Read all 172 final lines. Existing bridge connection, JSON/form/local data separation, browser draft persistence, notification forwarding and presentation context remain intact.", - "New ResourceAvailability contains only name:string and available:boolean. resourceAvailability sends extension.resources, rejects a non-array or malformed row, and projects exactly those two fields.", - "The SDK test proves a host-private path is not returned and available:'yes' is rejected. No host ResourceDescriptor, HTTP path or mutation privilege is exported.", - "mountPlugin still retains the existing app state while making it inert on unavailable non-retained contributions; retained controls and job/history methods were not altered. SDK/plugin-UI typecheck passed." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/components/BaseDialog.vue", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "566222c22f03c50915ef9ffce982ec535aa7c1e9117169bb7869017ca482b0ff", - "review_fingerprint": "566222c22f03c50915ef9ffce982ec535aa7c1e9117169bb7869017ca482b0ff", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Shared host/plugin dialog preserves a single stacked accessible-title identity, focus cycling, body scroll locking and close controls. Availability uses injected context, retains content/input and marks only body/footer inert while failed. Both inert bindings now omit the attribute when available instead of serializing false; this matches boolean HTML semantics without changing dialog dimensions.", - "evidence": [ - "Complete component read; a new jsdom regression first observed two inert attributes even while available, then passed available→unavailable→recovered with the same input node/value. Close control stays outside inert body/footer. No browser pixels or full focus/accessibility audit claimed.", - "artifacts/evidence/v027-ui-host-mechanism-review.json" - ] - }, - { - "path": "backend/pkg/extensionapi/ui/components/ConfirmDialog.vue", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "df495617216c500f5a88dd1929a3ed5f32b06f7ed5054fe20ae32de88925c57e", - "review_fingerprint": "df495617216c500f5a88dd1929a3ed5f32b06f7ed5054fe20ae32de88925c57e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "普通确认弹窗只转发明确confirm/cancel,文本经Vue插值、不执行HTML;底层共享BaseDialog管理关闭、焦点/禁用状态,按钮都是type=button;默认文案来自i18n。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/components/Icon.vue", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "1879d82804766ca5c6e06b869b8dd8e6dcd73e701a5b5b2d0cba625b9e10adf7", - "review_fingerprint": "1879d82804766ca5c6e06b869b8dd8e6dcd73e701a5b5b2d0cba625b9e10adf7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "固定SVG path常量与五档尺寸映射,name只能选择已有icon;不从外部URL加载、无v-html/脚本解析。完整读取图标数据与渲染层,不宣称做过像素/视觉验收或它在官方baseline相同路径存在。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/components/Pagination.vue", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "bb6f8f4b64faae567ca8071772939575c4e022c93b9acecaf731cea6e95f72ed", - "review_fingerprint": "bb6f8f4b64faae567ca8071772939575c4e022c93b9acecaf731cea6e95f72ed", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "移动/桌面展示、首尾省略、跳页和页容量事件均无业务IO;页容量取调用方合法5..1000整数去重排序,缺省回原10/20/50/100。goToPage阻止界外或同页提交,容量变更由宿主重置页码;total=0的总页数沿用0,不虚称新增空态改动。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/components/Select.vue", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "1e641b5fdda98f9fd23a3d2f03e818f03a78a3244e4e403143bd20182c65d9d3", - "review_fingerprint": "1e641b5fdda98f9fd23a3d2f03e818f03a78a3244e4e403143bd20182c65d9d3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文审阅查询/disabled分组、远程300ms搜索、portal定位/滚动监听、键盘/点击及样式。新增interactionDisabled合并显式disabled与注入插件可用性;禁用关闭teleport及待发搜索,实际select/clear/键盘也检查,保留modelValue。原选项/默认搜索/i18n/可创建值语义未变。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "E-SELECT-SOURCE/RED/GREEN/DIRECT/LINT document the bounded behavior repair." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/components/Toggle.vue", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "be2597b673b44d42370e8883e56e9ae4cae5ed1fd28147dcc8ea1c1c0ab4f2e9", - "review_fingerprint": "be2597b673b44d42370e8883e56e9ae4cae5ed1fd28147dcc8ea1c1c0ab4f2e9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "只用button role=switch、aria-checked和update:modelValue取反事件;原生button键盘行为与父级传入disabled属性保留。无业务数据或网络请求,非teleport区域由父级可用性/inert约束。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/components/dialogStack.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "9143ab0e87f9ee969415e91783b144cdac131a68dfa87e5af3054be054ee3b99", - "review_fingerprint": "9143ab0e87f9ee969415e91783b144cdac131a68dfa87e5af3054be054ee3b99", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "模块内唯一ID序列和shallowReactive栈,以splice触发更新;滚动锁最后一个弹窗退出才释放。普通层逐次+10,80以上gate固定并限制下层上限,同层后注册优先;BaseDialog据此独占Escape/Tab处理,作用域是当前页面/iframe。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/context.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "6bddea28274cab23e4c561f9621c792a2a7161a57776e9d5dac9b64f32f480f5", - "review_fingerprint": "6bddea28274cab23e4c561f9621c792a2a7161a57776e9d5dac9b64f32f480f5", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "仅导出两个Symbol类型化注入键,分别承载ComputedRef可用性和故障原因;无全局状态或权限判断复制。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/errors.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "5acf8b65031dbb27bf320cc5cba918416c3b5ce2a40c46dd137963afaf46d651", - "review_fingerprint": "5acf8b65031dbb27bf320cc5cba918416c3b5ce2a40c46dd137963afaf46d651", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "共享错误展示函数按reason/code与metadata作i18n,再按message/error/response字段回退;不发请求、不持久化,不插入HTML。payment字段label兼容映射只是展示,不带支付逻辑。数据源须是已有脱敏API错误,本函数不是密钥脱敏器。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/index.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "710109f89995a328025e692fbf9fbd236f01f4f39cc4685b82fe087e3a1b79d8", - "review_fingerprint": "710109f89995a328025e692fbf9fbd236f01f4f39cc4685b82fe087e3a1b79d8", - "review_status": "pending" - }, - { - "path": "backend/pkg/extensionapi/ui/media.ts", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "d20fac8a1ea48a898ead6f18a71ad534bd2f6880efd1865bcd708755b6e90b18", - "review_fingerprint": "d20fac8a1ea48a898ead6f18a71ad534bd2f6880efd1865bcd708755b6e90b18", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "只定义用户图像历史DTO及终态枚举,保留Blob/源图/mask和部分结果状态;无账户选择、网络/媒体持久化或功能开关副作用。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/tailwind.preset.mjs", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "ea9749df5775e86d7edfd2d564a6b184a99a6e347a0382994932dfc157e90273", - "review_fingerprint": "ea9749df5775e86d7edfd2d564a6b184a99a6e347a0382994932dfc157e90273", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整读226行构建预设;颜色/阴影/圆角/背景与动画均为CSS变量带原fallback、字体默认系统,darkMode=class;没有运行时函数执行或额外tailwind插件。业务主题资产与宿主共享语义样式通过变量边界组合,不进行动态URL拼接。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/theme.css", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "0fb960d4a77e9823ea8f1f94785294ccd4e138cb730f5550c68c5c481c99abc8", - "review_fingerprint": "0fb960d4a77e9823ea8f1f94785294ccd4e138cb730f5550c68c5c481c99abc8", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "只定义中性浅深色语义变量、系统字体和prefers-reduced-motion规则;未引用远程字体/图片/脚本。插件主题可覆盖变量,停用后保留这些基本颜色和减少动画偏好,视觉对比度/像素未测。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/ui/tsconfig.json", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "c2f772e24cba6336f91a92889679ea08582878addd709baa10d080cb86c0b3f4", - "review_fingerprint": "c2f772e24cba6336f91a92889679ea08582878addd709baa10d080cb86c0b3f4", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "SDK与七域UI一起使用现有frontend编译设置和Vite类型,仅纳入公开SDK及plugins/*/ui/src,排除测试文件与项目references避免重复构建;不将TypeScript路径配置当运行时访问权限。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-public-ui-control-review.json", - "No production behavior edit or test execution for this unchanged file." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/account_create.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "dffd9aba6bc9dca6cd6ffabd2af8ba2abde36f32d9579c9427ff407c1c1b67bd", - "review_fingerprint": "dffd9aba6bc9dca6cd6ffabd2af8ba2abde36f32d9579c9427ff407c1c1b67bd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文135行:公开创建声明与请求仅含有限默认目标、命名非秘密输入和包/定义/执行代次前置条件;解码拒绝未知字段、缺必需成员、尾随值以及除defaults.load_factor外的null,五默认项必须实际存在。原始credentials/Extra、任意路径和执行入口不在SDK中;平台/范围/端点的语义准入仍在host,不能把类型声明当授权。", - "evidence": [ - "artifacts/evidence/v027-account-create-integration-review.json#verification", - "artifacts/evidence/v027-astra-account-create-backend-review.json" - ] - }, - { - "path": "backend/pkg/extensionapi/v1/account_edit.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "0d7e7b77a91a1f952ea7b0377524f571488596517c667c3b21b942bb671a9509", - "review_fingerprint": "0d7e7b77a91a1f952ea7b0377524f571488596517c667c3b21b942bb671a9509", - "review_status": "pending" - }, - { - "path": "backend/pkg/extensionapi/v1/account_import.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "d0481fe1f2073c19c8076961de9422885195775de4ee4df08cc220940d8414dd", - "review_fingerprint": "d0481fe1f2073c19c8076961de9422885195775de4ee4df08cc220940d8414dd", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "account-tools", - "reason": "导入策略只接收有效性事实、账号ID集合及不透明身份摘要,返回逐项create/update/reject计划、目标分组和tracking意图。没有原始凭据/代理密码字段;宿主仍须逐项验证计划,不因类型定义而信任插件给出的ID。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/account_tools.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "6b3510029a6ff72cb12df47326c169c7ba871972013e293711a3d8d0a399414e", - "review_fingerprint": "6b3510029a6ff72cb12df47326c169c7ba871972013e293711a3d8d0a399414e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "account-tools", - "reason": "分类赋值/批量排序、推理选项和逐账号测试计划为显式数据结构;ExpectedMatchCount与HasFilters保留筛选快照语义。文本策略只传字符数与UTF8有效性,不复制用户正文;宿主目标和事务校验不由这些结构代替。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/account_view.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "7d47f48f342846e74fe692644b9d22bdd591581a97177349b789a5dda187d99f", - "review_fingerprint": "7d47f48f342846e74fe692644b9d22bdd591581a97177349b789a5dda187d99f", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文复核公开v1数据合同:固定source/slot、有限谓词/预设/布局/同包引用,无任意URL/SQL/组件路径;身份头不带搜索或账号资料,捕获query只进既有加密job载荷。自定义JSON解码拒绝未知字段、null和尾随值,并要求必需结构/preset query;没有宿主私有Account/凭据或执行逻辑。类型只提供合同,范围和能力仍由服务端校验。", - "evidence": [ - "artifacts/evidence/v027-account-view-integration-review.json#verification", - "Current complete source read plus exact frozen/current SHA verification; no full-application runtime claim." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/api.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "b1f1d3fd1fb34deba9fc5810bad3a9fd85a56c17559dc47f90fe4328db5c8852", - "review_fingerprint": "b1f1d3fd1fb34deba9fc5810bad3a9fd85a56c17559dc47f90fe4328db5c8852", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "全文328行:仅标准库依赖的进程无关SDK;十种扩展capability、有限slot/HostOperation、账号标量事实/不透明identity revision、调度提案、调用结果、state CAS、租约generation及handler接口清晰分离,没有service.Account/数据库对象导出。OutboundIdentity的Token/ProxyURL是有意保留的敏感凭据响应类型,实际host callback必须校验Credentials能力和真实ID;不是浏览器可提交的任意出网指令。Invocation.AccountID由宿主目标提供且用于cache分区,Admin适配会覆盖payload同名成员。Encode/Decode是普通JSON编解码,Decode本身不拒绝未知成员;声明严格性来自安装decoder和专用类型,不把SDK反序列化称作鉴权。未实现/未授予HostOperation由host switch default拒绝,无任意SQL、文件路径或命令后门。 本轮同SHA复核,未改源码或重复既有业务测试;原manifest/schema缺陷及修复在本报告单列,不能用本文件结论覆盖其他文件。", - "evidence": [ - "artifacts/evidence/v027-host-contract-final-integration-review.json#read_extent", - "artifacts/evidence/v027-host-contract-final-integration-review.json#evidence", - "artifacts/evidence/v027-astra-host-contract-full-review.json#read_extent" - ] - }, - { - "path": "backend/pkg/extensionapi/v1/catalog.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "a5cdb096eb9dd5708ae8b6939c79c493d45ce1471d01c87fad433b60d3f9441b", - "review_fingerprint": "a5cdb096eb9dd5708ae8b6939c79c493d45ce1471d01c87fad433b60d3f9441b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Full-file public-contract review: an optional account identity was added without changing catalog entry fields, limits, interfaces or protocol versions.", - "evidence": [ - "Read all 68 final lines. CatalogQuery.AccountID is int64 with json account_id,omitempty; zero preserves old non-account queries and real account callers must project their authorized ID.", - "Capacity types, safe-token limit, reference metadata and resolver interface remain unchanged. Host-only match constraints stay excluded from JSON.", - "The serialized query and Invocation carry the same ID in the focused host test; old shared-query callers continue to pass." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "3a941971dc7251dbed07b94cab906385110e1ae23785e5ae4effa20d6bfba064", - "review_fingerprint": "3a941971dc7251dbed07b94cab906385110e1ae23785e5ae4effa20d6bfba064", - "review_status": "reviewed", - "decision": "reference", - "owner": "core-extension-and-job-host", - "reason": "完整SDK前文件审查与本次完整增量合并复核;保留Deprecated业务常量以维持源码兼容,增量CindyPricingQuery.Images和CindyPricingSnapshot.CatalogSnapshot承载同一计价/目录快照,无任意URL、SQL或执行入口。", - "evidence": [ - "artifacts/evidence/v027-cindy-snapshot-integration-review.json", - "artifacts/evidence/v027-astra-cindy-independent-metadata-review.json", - "artifacts/evidence/v027-astra-cindy-snapshot-second-review.json", - "Deprecated business constants remain source-compatible; additive CindyPricingQuery.Images and CindyPricingSnapshot.CatalogSnapshot only." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy_account_test_plan.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "b15bb347d4506a9472a3433a183ce148096e96e9ed97bda449ab78f60dcac111", - "review_fingerprint": "b15bb347d4506a9472a3433a183ce148096e96e9ed97bda449ab78f60dcac111", - "review_status": "reviewed", - "decision": "adapter", - "owner": "core-extension-and-job-host", - "reason": "新固定 Method 和外层纯数据 DTO;未向旧 strict CatalogSnapshotV1 或计价 companion 增字段。 全文结论来自逐路径冻结审查,区域项未导入;实际测试、前代理报告与未运行边界见同一报告。", - "evidence": [ - "artifacts/evidence/v027-astra-single-test-policy-boundary-review.json#source_index:backend/pkg/extensionapi/v1/cindy_account_test_plan.go", - "artifacts/evidence/v027-astra-single-test-policy-boundary-review.json#validation", - "commit 7b4de3ae7; exact SHA rechecked at integration" - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy_alpha_search.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "3aa099b4d459fec99f6a1770992815ef83a824cc8196ef87f8458221a685f3be", - "review_fingerprint": "3aa099b4d459fec99f6a1770992815ef83a824cc8196ef87f8458221a685f3be", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "cindy-provider", - "reason": "Alpha search请求只有model,账号身份走Invocation信封。返回协议/模型/回退条件和搜索次数计划,不含URL、凭据或用户请求正文;允许与实际出站仍须在宿主验证。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy_catalog_snapshot.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "53c61bc857b645b3d5c3a4995a85b7db5299e0a6b0b2ab325c0ca0beba98386b", - "review_fingerprint": "53c61bc857b645b3d5c3a4995a85b7db5299e0a6b0b2ab325c0ca0beba98386b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整40行typed V1合同;metadata/default/image-controller/config/inventory/projections/mappings为明确值字段;版本号为协议版本而非编译进宿主的业务目录版本。", - "evidence": [ - "artifacts/evidence/v027-cindy-snapshot-integration-review.json", - "artifacts/evidence/v027-astra-cindy-independent-metadata-review.json", - "artifacts/evidence/v027-astra-cindy-snapshot-second-review.json", - "Complete 40-line typed V1 catalog contract; metadata/defaults/projections/mappings and independent image-controller reference." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy_clone.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "f0067c1cf7a0aa513693dc98117d5f3f4fedca2dad43ee1224444c5f99fd443e", - "review_fingerprint": "f0067c1cf7a0aa513693dc98117d5f3f4fedca2dad43ee1224444c5f99fd443e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "cindy-provider", - "reason": "nil原样返回,非nil复制标量结构并重新分配Sizes/Qualities两个slice;调用方修改公开图像选项不污染共享目录原切片。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy_codex.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "7302a5f472f87b7154beae20b3387dd57dc0203aa34eb05f4f9dff3270a44379", - "review_fingerprint": "7302a5f472f87b7154beae20b3387dd57dc0203aa34eb05f4f9dff3270a44379", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "cindy-provider", - "reason": "明确的Codex展示DTO保留reasoning levels、truncation、上下文、工具与媒体字段;Option型指针/any字段无omitempty以明确输出null。无调度/执行方法;这里不重新声称与最新远端Codex版本相同。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy_health.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "1bb27645277ba3ec7829b349f3dc4975b468453e7564b4c241a9d3e7b197adda", - "review_fingerprint": "1bb27645277ba3ec7829b349f3dc4975b468453e7564b4c241a9d3e7b197adda", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "cindy-provider", - "reason": "健康观察仅提供HTTP状态/JSON有效性和结构化type/code,未提供message/raw body/凭据;策略返回两个uint8分类,实际健康持久化与枚举含义仍在宿主/插件调用层验证。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy_management.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "f219221f812788f17c9aa8e9a1da5a58ef78dc47f16f791ab6cd0e0740459609", - "review_fingerprint": "f219221f812788f17c9aa8e9a1da5a58ef78dc47f16f791ab6cd0e0740459609", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "管理 DTO 仅包含身份摘要、状态、时间、显式 Key ID 与成员计数,不携带凭据原文或执行接口。", - "evidence": [ - "backend/internal/service/plugin_cindy_management_test.go", - ".downstream/implementation-v0.2.7.md#可复用验证" - ] - }, - { - "path": "backend/pkg/extensionapi/v1/cindy_probe.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "8e6aefa6e8fa7b5f58ac666c2e275b384aac4082820584744876dbce618e70b3", - "review_fingerprint": "8e6aefa6e8fa7b5f58ac666c2e275b384aac4082820584744876dbce618e70b3", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "cindy-provider", - "reason": "固定probe outcome枚举、两模型数组、输入/最大输出、stage/wasMarked和decision DTO保留持久阶段接口。无网络实现或任意执行入口;账号scope通过Invocation单独传递,不能由无账号Plan本身授权。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/codex_identity.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "b52f58bbba153d9765da7621addc98a9825007c77daa0570e2d28848c725eb13", - "review_fingerprint": "b52f58bbba153d9765da7621addc98a9825007c77daa0570e2d28848c725eb13", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "codex-runtime", - "reason": "身份/profile生成契约只包含系统/终端/sandbox/版本/seed及UA结果;宿主存储与凭据授权不进入类型实现。本文件没有随机数、磁盘或网络副作用。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/codex_recovery.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "4cf3d4b826cae146c1770807083349cab1416e26da91e7f550d5057ae89e0719", - "review_fingerprint": "4cf3d4b826cae146c1770807083349cab1416e26da91e7f550d5057ae89e0719", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "The additive SDK transmits only recovery facts and bounded replay rules. Structured framing keeps protected auth/quota statuses out of request-state rejection parsing even when recovery is disabled.", - "evidence": [ - "TestSignatureRejectionRemainsRequestScopedWhenPluginIsAbsent passed; independent recovery package passed" - ] - }, - { - "path": "backend/pkg/extensionapi/v1/codex_transport.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "f0a9135c56c44118f5355553e58b5dfafbfe700ea6b4153dd3ec20d45493705e", - "review_fingerprint": "f0a9135c56c44118f5355553e58b5dfafbfe700ea6b4153dd3ec20d45493705e", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "codex-runtime", - "reason": "传输计划输入仅method/path/content metadata与BodyPresent布尔值,输出Enabled/Compress;无用户body或任意目标URL,实际请求/重试/压缩由宿主负责。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/decision.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "27d34e796741175d3bcbaa712114929d55525e109e6b77863d61676185426701", - "review_fingerprint": "27d34e796741175d3bcbaa712114929d55525e109e6b77863d61676185426701", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整读取有界规则解释器:最多64规则、每规则1至16条件、字段/结果64字节与值256字节限制;只支持eq/ne/gte/lt,整型解析失败或缺字段不匹配,按顺序首条命中否则明确默认,无脚本/正则/IO。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/document.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "f1234459c5ddfe64e668825f7ed459e1ad56bdf8a1b4c41506c6c5604b436aea", - "review_fingerprint": "f1234459c5ddfe64e668825f7ed459e1ad56bdf8a1b4c41506c6c5604b436aea", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "UTF8/NUL/空白/字节上限校验后对原正文SHA256;不规范化或覆盖调用者文本,返回真实字节长度,无文件IO。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/document_path.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "f73f9d2af77026aad1c1a3cb23404c73c46330afce5337747f5713ed524549fa", - "review_fingerprint": "f73f9d2af77026aad1c1a3cb23404c73c46330afce5337747f5713ed524549fa", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "逻辑文档路径拒绝空/NUL/反斜线、ASCII控制字符、冒号等保留符、绝对路径、..逃逸及非规范重复分隔;拒绝尾空格/点及声明的Windows设备名;折叠函数单独做NFC/case fold。路径字符串校验不是符号链接/实际目录沙箱证明。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/image.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "ad0a36ad1960892b47a44a3012810c07e37e33c3b5827b3e525ef3dce56e1c59", - "review_fingerprint": "ad0a36ad1960892b47a44a3012810c07e37e33c3b5827b3e525ef3dce56e1c59", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "公开图像协议仅含请求事实与受限计划,没有正文、图片、凭据、文件路径或出站地址字段。", - "evidence": [ - "backend/internal/service/plugin_image_bridge_test.go", - ".downstream/implementation-v0.2.7.md#可复用验证" - ] - }, - { - "path": "backend/pkg/extensionapi/v1/observability.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "e129c15eccff695ddfca4631811694e281a9b75d6afc8e21dffeeecd85b35f3d", - "review_fingerprint": "e129c15eccff695ddfca4631811694e281a9b75d6afc8e21dffeeecd85b35f3d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "admin-observability", - "reason": "遥测/主题开关、分类表、每账号分协议计数和展示完成率是独立DTO;完成率可nil,未添加隐式零费用/成功断言,无原始请求或凭据字段。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/prompt.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "68be3dfafe8ba02e51d43f7ce6cdce9523afb5ac2502d3e8554397a9a2a3b1d9", - "review_fingerprint": "68be3dfafe8ba02e51d43f7ce6cdce9523afb5ac2502d3e8554397a9a2a3b1d9", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Full SDK file read. Target gains optional account_id only. Snapshot/application schemas remain unchanged; omitting a real account ID preserves the previous accountless preview/global-management contract.", - "evidence": [ - "artifacts/evidence/v027-astra-prompt-request-scope-review.json: exact phased failures, targeted RUN/PASS, carrier provenance and full-versus-partial file scope" - ] - }, - { - "path": "backend/pkg/extensionapi/v1/publication.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "9e1f3a5a200918fa15a650e5cfa04623da943f802ec807be53983e53b59cabec", - "review_fingerprint": "9e1f3a5a200918fa15a650e5cfa04623da943f802ec807be53983e53b59cabec", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "prompt-skills", - "reason": "发布/回滚和技能存储接口返回有界事实/摘要与计划,不直接执行文件操作。已追宿主validateRemoteSkillRegistryProfile固定source/HTTPS根与上限,planRemoteSkillStorage固定paired、摘要拼接候选键和六个slot;类型中的root/key不成为任意文件路径授权。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/publisher.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "4b1ffd888fc8e6db2ca6deaf7c990ca051db2b96bb6b43a553382c0297741cd0", - "review_fingerprint": "4b1ffd888fc8e6db2ca6deaf7c990ca051db2b96bb6b43a553382c0297741cd0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "嵌入同一 publisher.json,固定 key ID 对 codexrip namespace 生效;不内置私钥,也不为不同 plugin namespace 借用该正式根。", - "evidence": [ - "go:embed publisher.json", - "FirstPartyPublisher/FirstPartyPublisherKey", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/publisher.json", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "0e9b3a8037387404ed4bb3e29efd9fd4cb4f2d1aa3b34ee2856e3b5c6ab9c014", - "review_fingerprint": "0e9b3a8037387404ed4bb3e29efd9fd4cb4f2d1aa3b34ee2856e3b5c6ab9c014", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Contains only the stable codexrip-plugins-v1 public identity used by host and release code. The public key matches the approved existing publisher metadata; no private key material or temporary test identity appears, and neither field was changed.", - "evidence": [ - "Exact local JSON read; public metadata only. Live GitHub secret existence/value was not queried and is not reasserted as a current check.", - "artifacts/evidence/v027-plugin-package-static-review.json" - ] - }, - { - "path": "backend/pkg/extensionapi/v1/resources.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "edf03baef69028a644580d84b9dd6ece2998e51eb4e147ffc18bfe2215f48dfc", - "review_fingerprint": "edf03baef69028a644580d84b9dd6ece2998e51eb4e147ffc18bfe2215f48dfc", - "review_status": "pending" - }, - { - "path": "backend/pkg/extensionapi/v1/rpc.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "720b6f4b0603b840ca4804c553185f53036bcda0ed4e8e0deaac6b7247eb8fb3", - "review_fingerprint": "720b6f4b0603b840ca4804c553185f53036bcda0ed4e8e0deaac6b7247eb8fb3", - "review_status": "pending" - }, - { - "path": "backend/pkg/extensionapi/v1/rpc_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "92650b9ec4fb71c5e71d94eaa1f6d9d0d15fc5ddd7453a05d4a9d5184ab9a20b", - "review_fingerprint": "92650b9ec4fb71c5e71d94eaa1f6d9d0d15fc5ddd7453a05d4a9d5184ab9a20b", - "review_status": "pending" - }, - { - "path": "backend/pkg/extensionapi/v1/runtime.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "14347c8d268108feb7dd3d670009f265e21a2021ae17a976436a0859e4d1932b", - "review_fingerprint": "14347c8d268108feb7dd3d670009f265e21a2021ae17a976436a0859e4d1932b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整runtime源复核。继续用官方pluginv1 Serve/GetInfo/Health/Validate/Apply及GRPCBroker,不替换proto;新增原来被嵌入Unimplemented遮盖的TestConfig,先检查取消/请求体限额,再由Module验证配置并读取本地状态。返回显式未测试上游,不调用Apply/Invoke;失败只返回固定诊断,不回显原始内部错误。", - "evidence": [ - "Full code and precise red/green: artifacts/evidence/v027-runtime-config-diagnostic-review.json", - "Official TestConfig protobuf request/response shape is unchanged." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/runtime_config_test.go", - "candidate_owner": "core-extension-and-job-host", - "role": "test-or-fixture", - "present": true, - "content_sha256": "b45f8fc918aa2bb23b24e9b41b1b1b8901f45f789b6cd2e5ab65c983d129612d", - "review_fingerprint": "b45f8fc918aa2bb23b24e9b41b1b1b8901f45f789b6cd2e5ab65c983d129612d", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "两个新顶层/六个叶子目标先全部因Unimplemented失败,后全部通过。正控断言一次Validate+一次Status、零Apply/Invoke,状态与消息明确诊断范围;缺请求/超限/取消不调用模块,config或status错误不报告成功。内存模块,无网络/子进程或模型验证。", - "evidence": [ - "Full code and precise red/green: artifacts/evidence/v027-runtime-config-diagnostic-review.json", - "Official TestConfig protobuf request/response shape is unchanged." - ] - }, - { - "path": "backend/pkg/extensionapi/v1/skills.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "551554e01b22fda0bb8ed1359f980a98447e567c7e96db945ce23b346903ad99", - "review_fingerprint": "551554e01b22fda0bb8ed1359f980a98447e567c7e96db945ce23b346903ad99", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "prompt-skills", - "reason": "种子/候选/清单/来源摘要、chunk读取、文件类型计划和树校验结构全读。Candidate.Body json:-而Envelope显式承载策略所需种子正文;chunk的Path是注册包内逻辑路径,宿主/注册表负责归一和大小检查。字段本身不产生文件或网络副作用。", - "evidence": [ - "Full-file review: artifacts/evidence/v027-public-sdk-contract-review.json", - "Static source contract review; domain host policy/transaction validation remains separately scoped." - ] - }, - { - "path": "backend/pkg/pluginapi/v1/manifest.schema.json", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "c369f74ee40923a0c3451d5148bceb175a605967771aa1cdbe4a816064639f18", - "review_fingerprint": "c369f74ee40923a0c3451d5148bceb175a605967771aa1cdbe4a816064639f18", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "完整文件由先前1381行全文读取加d771c8b79完整三hunk差异复核构成(当前1384行)。contribution父properties新增all_accounts:boolean而保留additionalProperties:false;resources[].name和resource_action.resource同用宿主有限dash语法,不允许空段、路径或任意URL。Create/Edit自身all_accounts=false及原有限字段/枚举约束未改。原schema JSON语法绿不曾证明合同正确,本次明确以先前all_accounts与合法hyphen资源的red、当前源码差异、父级3方法green和七真实manifest标准Draft2020-12验证补证收口;source模板的空runtime/files只在验证fixture中填合成值,不冒充正式包构建。", - "evidence": [ - "artifacts/evidence/v027-host-contract-final-integration-review.json#read_extent", - "artifacts/evidence/v027-host-contract-final-integration-review.json#evidence", - "artifacts/evidence/v027-astra-host-contract-full-review.json#read_extent", - "artifacts/evidence/v027-astra-host-contract-resource-followup.json#findings", - "artifacts/evidence/v027-host-contract-final-integration-review.json#review_history_correction" - ] - }, - { - "path": "backend/pkg/pluginapi/v1/runtime.go", - "candidate_owner": "core-extension-and-job-host", - "role": "source", - "present": true, - "content_sha256": "e7d803472f585569cce2286630e33d89f4344ea50786b720e33e0191868287e2", - "review_fingerprint": "e7d803472f585569cce2286630e33d89f4344ea50786b720e33e0191868287e2", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "Protocol/Transport/UI/HostService 版本均为1;oauth_transport 注册和既有 magic-cookie handshake 保留,先注册官方 TransportPlugin 服务,再可选附加 extension/host broker。", - "evidence": [ - "protocol constants", - "HandshakeConfig", - "GRPCServer official registration before additional services", - "ClientPluginMap/Serve", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": "backend/resources/model-pricing/model_prices_and_context_window.json", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "a8c0b50ca647d7779bed660ab25014a03ec20bde1984b020fdd0ee951b3650fa", - "review_fingerprint": "a8c0b50ca647d7779bed660ab25014a03ec20bde1984b020fdd0ee951b3650fa", - "review_status": "reviewed", - "decision": "core-correctness", - "owner": "core-quota-and-protocol", - "reason": "LiteLLM 格式的模型价格与上下文窗口兜底目录(config.pricing.fallback_file 默认指向此文件,远端 model-price-repo 优先)。全文 203 个模型条目(openai 128、vertex_ai-language-models 32、anthropic 23、gemini 10、deepseek 4、vertex_ai-embedding 3、text-completion-openai 2、bedrock 1),字段为 per-token 价格(含 flex/priority/batches/above_200k|272k 分档)、缓存读写价、max_*_tokens、mode、supported_endpoints/modalities 与 supports_* 能力位;末尾 4 个 gpt-image-2.5-* 条目缩进不同但与上游相同。以 Python 逐键比对上游 aea725f:0 新增、0 删除、4 处变更——deepseek-flash、deepseek-v4-flash、deepseek-v4-flash-vision-exp、deepseek-v4-pro 移除了 input_cost_per_token 与 output_cost_per_token(其余字段不变)。下游 DeepSeek 有效价改由 service/deepseek_pricing.go 官方价卡经 pricing_service.mergeDeepSeekPricing/lookupDeepseekPricingLocked 与 billing_service.deepseekOfficialPrice 注入(git log:fix(billing) 统一 DeepSeek 身份与有效价、峰谷价),兜底文件因此不再携带会与之冲突的平价。属宿主计费数据的正确性对齐;未核对价格数值本身。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S46-backend-pkg-server-3-review.json", - "L748-L829 四个 deepseek 条目(仅 cache_read_input_token_cost、容量、能力位,无 input/output_cost_per_token);结构比对脚本输出:upstream 203 / current 203,ADDED 0,REMOVED 0,CHANGED 4(flash 系 input 1.5e-07→缺失、output 6e-07→缺失;pro 6.6e-07/1.98e-06→缺失)。", - "调用链:service/pricing_service.go L973 mergeDeepSeekPricing、L1141/L1219 lookupDeepseekPricingLocked;billing_service.go L884-L885 deepseekOfficialPrice;config/config.go L2335 fallback_file 默认路径。", - "L1-L6407 全文分 13 段(每段 ≤500 行)读完;静态阅读,未执行测试、未核对官方价格。" - ] - }, - { - "path": "backend/scripts/build-development-plugins.sh", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "e1b605fcbf2a3f4968919b567da98f887dd7104ed81152c331da79c456c26bf0", - "review_fingerprint": "e1b605fcbf2a3f4968919b567da98f887dd7104ed81152c331da79c456c26bf0", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core-extension-and-job-host", - "reason": "显式拒绝正式 signing Secret;临时目录生成 development key,key-id=codexrip-development,退出清理临时 key。使用 -development 验证,只被 Docker development stage 使用。", - "evidence": [ - "release secret nonempty guard", - "temporary key/trap", - "development-only verification", - "Full-file scope recorded in artifacts/evidence/v027-astra-release-supply-chain-review.json. No real release/signing/CI/deployment is inferred from this source review." - ] - }, - { - "path": "deploy/.env.example", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "314526cbdec4cf4d147ca105b900ef7e4b32516f58ef2526aa29e994522bbd55", - "review_fingerprint": "314526cbdec4cf4d147ca105b900ef7e4b32516f58ef2526aa29e994522bbd55", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "容器环境变量模板。下游相对上游新增 46 行:(1) SUB2API_REMOTE_SKILL_REGISTRY_HOST_PATH(配对提示词/树发布目录的宿主机路径,仅 docker-compose.yml 的卷挂载消费;插入位置落在日志段 LOG_SERVICE_NAME 与 LOG_ENV 之间,属排版瑕疵);(2) 三个 OpenAI 网关开关 GATEWAY_OPENAI_CODEX_REQUEST_ZSTD=true、GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED=false、GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE=off;(3) Cindy 分阶段灰度五个开关(BALANCE_DETECTION=true,其余 false)与已注释的 GATEWAY_CINDY_IMAGE_STUDIO_ENABLED 一次性回退名;(4) 注释掉的 SECURITY_ACCOUNT_API_KEY_REVEAL_PASSWORD 占位并提示勿提交真实密码。已核对全部新变量在四个 compose 文件中透传,并对应 backend/internal/config/config.go 的 viper 默认键(AutomaticEnv + '.'→'_'),Cindy 五值由 cindy_feature_flags.go / image_studio_feature_flags.go 读取,deploy/tests/cindy-rollout-defaults-test.sh 锁定这些示例值。文件不含真实密钥(POSTGRES_PASSWORD 为占位符)。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +46 lines at L55-L58, L293-L308, L369-L388, L456-L458; upstream blob 47f249b6. Whole 518-line file read in two chunks.", - "Consumer check (rg): SUB2API_REMOTE_SKILL_REGISTRY_HOST_PATH -> deploy/docker-compose.yml only; the three GATEWAY_OPENAI_*/ACCOUNT_TRAFFIC vars -> all four compose files + config.go L987/L994/L1061 (mapstructure openai_codex_request_zstd / openai_request_integrity_mode / account_traffic_telemetry_disabled) with SetDefault at L2419-L2421 and AutomaticEnv at L1833-L1834; SECURITY_ACCOUNT_API_KEY_REVEAL_PASSWORD -> config.go L738 + docker-compose.yml/.local.yml.", - "Cindy flags: backend/internal/service/cindy_feature_flags.go L12 and backend/internal/config/image_studio_feature_flags.go; deploy/tests/cindy-rollout-defaults-test.sh L15-L20 asserts exactly these example lines (BALANCE_DETECTION=true, others false, commented CINDY_IMAGE_STUDIO).", - "Static read only; no container or compose command executed." - ] - }, - { - "path": "deploy/Dockerfile", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "498548046cef37520bf5d0be15c6f3a0a62bf410d4caf74f95a08c8484b61948", - "review_fingerprint": "498548046cef37520bf5d0be15c6f3a0a62bf410d4caf74f95a08c8484b61948", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "三阶段构建镜像(node:24 前端以 pnpm@9.15.9 构建并带入 docs/legal/*.md?raw、golang:1.27.0 后端 -tags embed 构建、alpine 运行时非 root 用户)。下游相对上游是与 Dockerfile.goreleaser 完全同构的三处改动:复制 THIRD_PARTY_NOTICES.md 到 /app、新建可写的 /app/skill-registry、chown 从递归 /app 收窄为二进制+data+skill-registry。其余(GOPROXY 国内镜像默认值、resolve-version.sh 版本优先级、wget 健康检查、entrypoint)与上游一致。未构建镜像,静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +4/-2 at L109 (COPY THIRD_PARTY_NOTICES.md) and L111-L113 (mkdir /app/data /app/skill-registry; chown sub2api:sub2api binary, data, skill-registry); upstream blob ab312c48. Whole 128-line file read.", - "Consumers of the new directory: deploy/docker-entrypoint.sh L8-L10 (mkdir/chown at start); same stanza in Dockerfile L176-L180 and Dockerfile.goreleaser L48-L52.", - "Toolchain pin L10 golang:1.27.0-alpine matches backend/go.mod; no secrets or hosts in the file.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": "deploy/README.md", - "candidate_owner": "operations", - "role": "documentation", - "present": true, - "content_sha256": "14eb409446930c467e7647af4d7b64c031146a06f1cf11a2079804d93dd4b932", - "review_fingerprint": "14eb409446930c467e7647af4d7b64c031146a06f1cf11a2079804d93dd4b932", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "部署目录说明文档(Docker Compose/Apple container/二进制安装、自动初始化、数据库恢复与迁移说明、Gemini OAuth 三种方式、故障排查、TLS 指纹配置)。下游相对上游新增 L177-L294 “Cindy staged rollout” 一节:五个进程级开关及推荐首次部署值、production-deploy.yml 三种 operation(deploy/reconcile-runtime/rollback)的 gh workflow run 示例、宿主机把五元组持久化到 /opt/sub2api/docker-compose.cindy-rollout.yml、guard-first 迁移期对旧三元组的映射、interrupt_business 排空流程,以及 GATEWAY_CINDY_IMAGE_STUDIO_ENABLED 一次性回退规则。与 production-deploy.yml 核对:三种 remote_command 形态一致;但该节称工作流“只发送 deploy cindy=...”,未覆盖工作流后来增加的 deploy-preserve/runtime=preserve、resource= 与 maintenance=interrupt 后缀(findings,低;DOWNSTREAM.md 已提及 deploy-preserve)。表中 BALANCE_DETECTION 推荐首次为 false 而 .env.example 示例值为 true(由 cindy-rollout-defaults-test.sh 锁定),属阶段性建议与示例默认的差异。纯文档,静态阅读,未对照运行主机。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +119 lines, all inside the new 'Cindy staged rollout' section L177-L294; upstream blob f38257e3. Whole 777-line file read in two chunks (L1-L500, L501-L777).", - "Cross-check with .github/workflows/production-deploy.yml: L316 'deploy ${IMAGE_REF} ${CINDY_ROLLOUT}', L328 'reconcile-runtime ...', L337 'rollback ${IMAGE_REF} from=${EXPECTED_CURRENT_IMAGE_REF} ${CINDY_ROLLOUT}' match the documented forced commands; L314 'deploy ${IMAGE_REF} runtime=preserve', L317-L322 resource=/maintenance= suffixes are not described in this section.", - "Other sections (L1-L176, L296-L777: file table, Apple container, auto-setup, DB recovery, datamanagementd, env table, Gemini OAuth, binary install, troubleshooting, TLS fingerprint) are unchanged upstream text.", - "Static read only; documentation content was not verified against a running system." - ] - }, - { - "path": "deploy/config.example.yaml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "c2a7a33cd56cb22b9a72862010a8dc5759bd45a365583d615b0c6fe1c6cdc78b", - "review_fingerprint": "c2a7a33cd56cb22b9a72862010a8dc5759bd45a365583d615b0c6fe1c6cdc78b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "二进制部署用完整配置模板(1292 行,中英双语注释)。下游相对上游 +45/-2:(1) security 下新增注释掉的 account_api_key_reveal_password 及其环境变量名;(2) gateway 下新增 openai_codex_request_zstd: true、account_traffic_telemetry_disabled: false、openai_request_integrity_mode: off 三个开关;(3) 新增 openai_codex_ticket 块(默认 enabled: false,target_length 292、ttl 3600、refresh_before 600、harvest_proxy_url 空、探测间隔 6s/单次超时 25s、fail_closed true、models gpt-6-astra/gpt-5.6-sol),说明 292 打票代理与后台可覆盖;(4) openai_ws 下新增 cindy_http_to_wsv2_enabled: false 并改写 force_http 注释。已核对全部新键在 backend/internal/config/config.go 有 mapstructure 绑定与 viper 默认值。文件只含占位符(数据库密码、JWT、admin123 均为上游示例),无真实凭据;模板本身不决定 292 ticket 业务归属(codex-runtime 域 vs 宿主),那由 config.go/service 层的审阅决定。静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: L125-L127 (commented account_api_key_reveal_password), L265-L277 (three gateway switches), L330-L354 (openai_codex_ticket block), L377-L381 (cindy_http_to_wsv2_enabled + force_http comment rewrite); upstream blob e93f6c96. Whole file read in three chunks (L1-L500, L501-L1000, L1001-L1292).", - "Binding check (rg backend/internal/config): OpenAICodexTicket mapstructure 'openai_codex_ticket' at config.go L1024 with fields target_length/refresh_before_seconds/harvest_proxy_url/harvest_probe_interval_seconds/harvest_attempt_timeout_seconds/fail_closed at L1247-L1253 and models default L2435; CindyHTTPToWSV2Enabled L1284 + SetDefault L2446; the three gateway switches at L987/L994/L1061 with defaults L2419-L2421; AccountAPIKeyRevealPassword L738 (json:\"-\").", - "Unchanged upstream sections read in full: server/h2c, webauthn, cors, security url_allowlist/csp/proxy_probe, gateway openai_ws pool + scheduler weights, log, token_refresh, api_key_auth_cache, dashboards, idempotency, database, redis, ops, jwt, totp, linuxdo/oidc SSO, default, rate_limit, plugins (allow_unsigned false, trusted_publishers), pricing, billing, turnstile, gemini, update, image_storage.", - "Static read only; no config loaded, no process started." - ] - }, - { - "path": "deploy/docker-compose.dev.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "cc3c951be1575f20294f4205625002b7c00ee85e8633497ebb63ba6f96549886", - "review_fingerprint": "cc3c951be1575f20294f4205625002b7c00ee85e8633497ebb63ba6f96549886", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "本地源码构建用 Compose(context: .. + 根 Dockerfile;中国大陆开发代理默认值 host.docker.internal:7897 为上游内容)。下游相对上游 +21/-10:新增 ./skill-registry-data:/app/skill-registry:Z 卷;新增 GATEWAY_OPENAI_CODEX_REQUEST_ZSTD / GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED / GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE 三个透传(默认值与后端一致);新增 Cindy 四个灰度开关透传以及 GATEWAY_IMAGE_STUDIO_ENABLED / GATEWAY_CINDY_IMAGE_STUDIO_ENABLED 的空默认透传;其余差异只是把 BATCH_IMAGE_* 九行与 GATEWAY_MAX_BODY_SIZE 挪到前面(内容不变,Vertex 项目/桶默认值为上游既有)。已核对空字符串透传不会破坏“一次性回退”语义:backend/internal/config/image_studio_feature_flags.go L15-L16、L45 显式把空值视为未配置。无真实密钥(POSTGRES_PASSWORD 为 :? 必填占位)。静态阅读,未启动容器。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +1 volume L26, +3 gateway env L71-L73, +6 Cindy/Image Studio env L104-L109, BATCH_IMAGE_* and GATEWAY_MAX_BODY_SIZE relocated (removed L87/L98-L106 of upstream, re-added L59-L69); upstream blob c2a2ac92. Whole 184-line file read.", - "Every new env var maps to a backend key: config.go L987/L994/L1061 (gateway switches), service/cindy_feature_flags.go (four Cindy flags), config/image_studio_feature_flags.go (studio flags; optionalBooleanEnvironment treats '' as unconfigured).", - "Postgres/Redis services, healthchecks and the redis-server command block are unchanged upstream text; security_opt no-new-privileges retained.", - "Static read only; no compose command executed." - ] - }, - { - "path": "deploy/docker-compose.local.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "11613bcbd9912ca5c64c1dfb3d9a8da7cc9299bfb263bb09c9a98de28802dc16", - "review_fingerprint": "11613bcbd9912ca5c64c1dfb3d9a8da7cc9299bfb263bb09c9a98de28802dc16", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "本地目录版 Compose(./data、./postgres_data、./redis_data 绑定挂载,:Z SELinux 标签;docker-deploy.sh 推荐部署形态)。下游相对上游 +15/-1:新增 ./skill-registry-data:/app/skill-registry:Z 卷;安全段新增 SECURITY_ACCOUNT_API_KEY_REVEAL_PASSWORD 透传(空默认=关闭 API Key 显示开关);新增 GATEWAY_OPENAI_CODEX_REQUEST_ZSTD / GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED / GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE 三个透传与六个 Cindy/Image Studio 透传;GATEWAY_MAX_BODY_SIZE 仅前移。Postgres/Redis 服务、healthcheck、redis-server 命令块与上游一致;所有密钥由 .env 注入,文件内无真实凭据。静态阅读,未启动容器。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +1 volume L41, +2 security L154-L155, +3 gateway L173-L175, +6 Cindy/Studio L206-L211, GATEWAY_MAX_BODY_SIZE relocated to L171; upstream blob 8a14f4d7. Whole 308-line file read.", - "All added variables resolve to backend keys (config.go L738/L987/L994/L1061, cindy_feature_flags.go, image_studio_feature_flags.go); identical passthrough set exists in docker-compose.yml, .standalone.yml and .dev.yml.", - "Unchanged upstream text: services postgres (L237-L263) and redis (L268-L301), network, healthchecks, security_opt no-new-privileges, ulimits.", - "Static read only; no compose command executed." - ] - }, - { - "path": "deploy/docker-compose.standalone.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "7444ca7808122e1e5604a84941931d08a083afe6e0882e538830d83ebe5c5351", - "review_fingerprint": "7444ca7808122e1e5604a84941931d08a083afe6e0882e538830d83ebe5c5351", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "仅运行 Sub2API 应用、外接 PostgreSQL/Redis 的 Compose。下游相对上游 +14/-1:新增命名卷 sub2api_skill_registry 挂到 /app/skill-registry 并在 volumes 段声明;新增 GATEWAY_OPENAI_CODEX_REQUEST_ZSTD / GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED / GATEWAY_OPENAI_REQUEST_INTEGRITY_MODE 三个透传;新增 Cindy 四个灰度开关与 Image Studio 两个空默认透传;GATEWAY_MAX_BODY_SIZE 仅前移。数据库/Redis 主机与密码为 :? 必填占位,无真实凭据;与 dev/local/yml 三个文件的同类改动一致。注意本文件未透传 SECURITY_ACCOUNT_API_KEY_REVEAL_PASSWORD(standalone 部署需自行注入才能启用 API Key 显示开关)也未使用 SUB2API_REMOTE_SKILL_REGISTRY_HOST_PATH(命名卷无需)。静态阅读,未启动容器。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +1 volume L28, +1 GATEWAY_MAX_BODY_SIZE relocation L115, +3 gateway L117-L119, +6 Cindy/Studio L150-L155, +2 volume declaration L174-L175; upstream blob 7273dd0f. Whole 175-line file read.", - "Variable set matches the other compose files except SECURITY_ACCOUNT_API_KEY_REVEAL_PASSWORD (present only in docker-compose.yml L154 and docker-compose.local.yml L155); documented in reason as a deliberate gap to know about, not a defect.", - "Unchanged upstream text: extra_hosts host.docker.internal, required DATABASE_HOST/REDIS_HOST, Gemini/Antigravity secret passthroughs, healthcheck.", - "Static read only; no compose command executed." - ] - }, - { - "path": "deploy/docker-compose.yml", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "91f5eace5914de833dfe582dfaf73e5b05401d2a47c356e0eb4ff762ccdb17fc", - "review_fingerprint": "91f5eace5914de833dfe582dfaf73e5b05401d2a47c356e0eb4ff762ccdb17fc", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "命名卷版 Compose(生产宿主机 /opt/sub2api 使用的基础文件)。下游相对上游 +17/-1:新增 skill-registry 绑定挂载 ${SUB2API_REMOTE_SKILL_REGISTRY_HOST_PATH:-./skill-registry-data}:/app/skill-registry(全仓库唯一消费该变量之处,生产为 /opt/sub2api/skill-registry,注释说明 Nginx 不直接读该目录);安全段新增 SECURITY_ACCOUNT_API_KEY_REVEAL_PASSWORD 透传;新增三个 OpenAI 网关开关与六个 Cindy/Image Studio 透传;GATEWAY_MAX_BODY_SIZE 前移。Postgres 调参 command、PGDATA 说明、120s start_period、Redis 命令块、ALIPAY_MOBILE_PRECREATE_DEEP_LINK 等为上游内容。所有密钥由 .env 注入,文件内无真实凭据。静态阅读,未启动容器。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +3 volume lines L33-L35, +2 security L153-L154, +3 gateway L172-L174, +6 Cindy/Studio L205-L210, GATEWAY_MAX_BODY_SIZE relocated to L170; upstream blob e6b84a54. Whole 345-line file read.", - "SUB2API_REMOTE_SKILL_REGISTRY_HOST_PATH is documented in deploy/.env.example L55-L58 and consumed only here (rg); production-deploy.yml never edits this file, it dispatches the restricted host updater which owns /opt/sub2api compose state (see deploy/README.md L218-L221).", - "Unchanged upstream text: postgres command tuning L259-L264, PGDATA note L268-L271, healthcheck with psql SELECT 1 L279-L287, redis block L294-L328, volumes/networks.", - "Static read only; no compose command executed." - ] - }, - { - "path": "deploy/docker-entrypoint.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "d1f65105da389deabba1abbee8db07c2c149dd6639ce141c30d341485daae5d7", - "review_fingerprint": "d1f65105da389deabba1abbee8db07c2c149dd6639ce141c30d341485daae5d7", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "operations", - "reason": "容器入口脚本:以 root 启动时先修复可写目录权限再用 su-exec 以 sub2api 身份重新执行自身,首参数为 --flag 时补上 /app/sub2api 以兼容旧 ENTRYPOINT。下游相对上游 3 行改动:mkdir 与 chown -R 由只处理 /app/data 扩为 /app/data 与 /app/skill-registry(配合三个 Dockerfile 新建的目录和四个 compose 文件新增的挂载),注释相应改写。chown 失败仍 || true 以容忍只读挂载;无凭据、无网络。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: L4 comment, L8 'mkdir -p /app/data /app/skill-registry', L10 'chown -R sub2api:sub2api /app/data /app/skill-registry 2>/dev/null || true'; upstream blob 47ab6bf1. Whole 23-line file read.", - "Consumers: Dockerfile / deploy/Dockerfile / Dockerfile.goreleaser copy it to /app/docker-entrypoint.sh and use it as ENTRYPOINT; compose files mount /app/skill-registry (named volume or bind) which this script makes writable for the non-root user.", - "Behaviour outside the delta (su-exec re-exec L13, flag compatibility L19-L21, exec \"$@\" L23) is unchanged upstream logic.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": "deploy/plugin-bundle/README.md", - "candidate_owner": "operations", - "role": "documentation", - "present": true, - "content_sha256": "60833ab02cb7beb115203adad6458b3886baf6dd58bf6d3534553dd3d3d157a7", - "review_fingerprint": "60833ab02cb7beb115203adad6458b3886baf6dd58bf6d3534553dd3d3d157a7", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "下游新增的 5 行中文说明:deploy/plugin-bundle/current/ 是正式发布工作流生成的签名 .s2plugin 包与 lock.json 的输出目录(不提交源码,.gitignore L194 忽略),镜像以 PLUGIN_BUNDLE_STAGE=plugin-bundle-release 阶段校验后原样复制,目录不保存私钥;本地与候选镜像使用独立的开发签名阶段,正式 Codexrip 版本拒绝开发发布者签名的集合。与 downstream-release.yml L141-L142/L209/L228、plugin-release.yml L134-L154、Dockerfile L120 'COPY deploy/plugin-bundle/ /bundle/' 和 release_preflight.py L145 的实际用法一致;.dockerignore L13 放行本 README 进入构建上下文。纯文档,静态阅读。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "New downstream file (no upstream blob); whole 5-line file read.", - "Consumers (rg 'deploy/plugin-bundle'): .dockerignore L13, .gitignore L194, .github/scripts/release_preflight.py L145, downstream-release.yml L141-L142/L209/L228, plugin-release.yml L134-L154, Dockerfile L120, docs/PLUGIN_DEVELOPMENT.md L126.", - "Statement 'this directory stores no private keys' is consistent with .gitignore L193 '/plugins/**/*.key' and with the -key-id codexrip-plugins-v1 signing done inside the release workflow.", - "Static read only; documentation content was not verified against a running system." - ] - }, - { - "path": "deploy/tests/cindy-rollout-defaults-test.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "4f47156405f0279d3048129f8260f13eca7e167b687d6dd311bd8c68b2819ee7", - "review_fingerprint": "4f47156405f0279d3048129f8260f13eca7e167b687d6dd311bd8c68b2819ee7", - "review_status": "pending" - }, - { - "path": "deploy/tests/docker-compose-gateway-env-test.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "a4f9f41b6dbb6ebaef3d6e778b25fdc1d5763a0a239b14bd3e257c2c2d269aca", - "review_fingerprint": "a4f9f41b6dbb6ebaef3d6e778b25fdc1d5763a0a239b14bd3e257c2c2d269aca", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "POSIX sh 契约测试:用 awk 抽取 deploy/.env.example 中所有 GATEWAY_*= 变量,逐个断言四个 compose 文件(yml/local/standalone/dev)恰好各有一行 '- KEY=${KEY:-<示例值>}' 且该键只出现一次,个别键用后端默认值覆盖示例值(MAX_CONNS_PER_HOST 1024、MAX_IDLE_CONNS 2560、MAX_IDLE_CONNS_PER_HOST 120)。下游相对上游 +1 行:GATEWAY_IMAGE_STUDIO_ENABLED 的期望回退改为空字符串,与 compose 中 ${GATEWAY_IMAGE_STUDIO_ENABLED:-} 的“空即未配置、允许一次性回退”语义一致。已对照本切片读到的 .env.example 与四个 compose 文件静态核对:三个新 OpenAI 开关(true/false/off)、四个 Cindy 开关(true/false/false/false)、GATEWAY_MAX_BODY_SIZE 的回退值均与示例一致;注释掉的 GATEWAY_CINDY_IMAGE_STUDIO_ENABLED 不以 GATEWAY_ 开头行出现故不在本测试范围。由 backend-ci.yml L23 以 /bin/sh 执行。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: +1 line L35 'GATEWAY_IMAGE_STUDIO_ENABLED) value= ;;'; upstream blob f068410b. Whole 48-line file read.", - "Mechanics: L13-L18 awk over deploy/.env.example, L20-L46 loop over 4 compose files with grep -Fxc for the exact fallback line and grep -Ec for key uniqueness; mktemp + trap cleanup L7-L11.", - "Static cross-check against files read in this slice: .env.example L297/L302/L308/L375-L387 vs compose lines e.g. docker-compose.yml L172-L174, L205-L209 all match; consumer .github/workflows/backend-ci.yml L23.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": "deploy/tests/docker-runtime-resources-test.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "90f1dfeda315a07c1e55df5f1ef77c0aeb2421f62e2907264bcff569de45d405", - "review_fingerprint": "90f1dfeda315a07c1e55df5f1ef77c0aeb2421f62e2907264bcff569de45d405", - "review_status": "reviewed", - "decision": "reference", - "owner": "operations", - "reason": "POSIX sh 契约测试:断言 backend/resources/model-pricing/model_prices_and_context_window.json 存在且非空,Dockerfile.goreleaser 与 deploy/Dockerfile 各含把 backend/resources 复制到 /app/resources 的确切 COPY 行,.goreleaser.yaml 有 4 处、.goreleaser.simple.yaml 有 1 处 ' - backend/resources'。下游相对上游仅把 assert_line/assert_count 改为先 tr -d '\\r' 再 grep,使 CRLF 检出(Windows 工作区)下也能匹配,属测试工具健壮性修正而非核心行为变更。由 backend-ci.yml L24 以 /bin/sh 执行。静态阅读,未执行。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S47-ops-docs-1-review.json", - "git diff vs aea725f: L15 and L22 add 'tr -d '\\r' <\"$file\" |' before grep -Fqx / grep -Fxc; upstream blob 4e7480d4. Whole 34-line file read.", - "Assertions L26-L32 reference Dockerfile.goreleaser L47 and deploy/Dockerfile L108 (both read in this slice and matching the asserted COPY text) plus .goreleaser*.yaml counts (out of slice, not verified here).", - "Consumer: .github/workflows/backend-ci.yml L24.", - "Static read only: the script/workflow was not executed, no test, build, Docker or network action was taken." - ] - }, - { - "path": "deploy/tests/production-deploy-workflow-test.sh", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "1ca6ab58a9f5c002c7e26290571e37297c1ca37967424ebb0e692b8f1e01899f", - "review_fingerprint": "1ca6ab58a9f5c002c7e26290571e37297c1ca37967424ebb0e692b8f1e01899f", - "review_status": "pending" - }, - { - "path": "deploy/tests/test_verify_business_system_prompt_bundle.py", - "candidate_owner": "operations", - "role": "source", - "present": true, - "content_sha256": "e90bafec78791c3e043a280d9fad313cfca28eccec6cfdac62873b5b54ee0611", - "review_fingerprint": "e90bafec78791c3e043a280d9fad313cfca28eccec6cfdac62873b5b54ee0611", - "review_status": "pending" - }, - { - "path": "docs/PLUGIN_DEVELOPMENT.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "957d36e86583283d4b1adee856dc341cc22b57e2b44512fbd380ec0c3d5f0edc", - "review_fingerprint": "957d36e86583283d4b1adee856dc341cc22b57e2b44512fbd380ec0c3d5f0edc", - "review_status": "pending" - }, - { - "path": "docs/channel-monitor-v2-safe-defaults.md", - "candidate_owner": "documentation-and-history", - "role": "documentation", - "present": true, - "content_sha256": "0b552c4cfcd546ae8bd46670e5486418b3353576d93fb37d1584b0cde1e1a625", - "review_fingerprint": "0b552c4cfcd546ae8bd46670e5486418b3353576d93fb37d1584b0cde1e1a625", - "review_status": "pending" - }, - { - "path": "frontend/index.html", - "candidate_owner": "mixed-requires-review", - "role": "source", - "present": true, - "content_sha256": "948d2e03723d93c74a6b19e6202e18fb455398e151231c58dafc9f2e4e447d6b", - "review_fingerprint": "948d2e03723d93c74a6b19e6202e18fb455398e151231c58dafc9f2e4e447d6b", - "review_status": "reviewed", - "decision": "core-mechanism", - "owner": "core", - "reason": "宿主 SPA 入口页。下游相对上游只新增一段带 nonce=\"__CSP_NONCE_VALUE__\" 的内联预绘主题脚本(读 localStorage 'theme' 或 prefers-color-scheme,在 CSS 绘制前给 加 dark 类以避免首屏闪白),逻辑与 main.ts initThemeClass 一致,是宿主通用机制而非任何插件业务。nonce 占位符由 backend/internal/web/embed_on.go 的 replaceNoncePlaceholder 在请求时替换,已确认存在。静态阅读,未运行开发服务器或浏览器。", - "evidence": [ - "Full-file static review: artifacts/evidence/v027-claude-S43-frontend-root-1-review.json", - "Delta vs aea725f: a single added line L7 ``; the other 13 lines (lang zh-CN, /logo.svg icon, viewport meta, title, #app, /src/main.ts module script) are upstream-identical. Last commit 87b198554 'fix(ui): give the pre-paint theme script the CSP nonce placeholder (#173)'.", - "CSP nonce check PASSED: the only inline