fix: make lifecycle rule activation auditable - #1551
Conversation
|
Warning Review limit reached
Next review available in: 31 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (61)
📝 WalkthroughWalkthrough버전 기반 라이프사이클 룰 등록·활성화와 낙관적 상태 전이, 드라이런 평가, 실행 버전 증빙, 진단 정보, 문제 코드 및 공개 API 문서가 추가되었습니다. Changes라이프사이클 룰 버전 제어
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant Registry as LifecycleRuleRegistry
participant Store as InMemoryLifecycleRuleStateStore
participant Evaluator as LifecycleRuleEvaluator
participant DryRunStore as InMemoryLifecycleDryRunStore
participant Diagnostics as LifecycleDiagnosticsProvider
Operator->>Registry: registerVersion(input)
Registry->>Store: saveRegistration(record)
Operator->>Registry: activate(request)
Registry->>Store: applyCommand(request)
Operator->>Evaluator: dryRun(input)
Evaluator->>Registry: getRegistrationState(ruleId, version)
Evaluator->>DryRunStore: save(result)
Diagnostics->>DryRunStore: list(options)
Diagnostics-->>Operator: health details
Possibly related issues
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📊 Benchmark Results✅ All benchmarks passed
Updated: 2026-07-25T22:21:50.968Z · Commit: 522ec46 |
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/lifecycle-core/src/libs/diagnostics/LifecycleDiagnosticsProvider.ts (1)
136-150: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win저하 원인을 상태 메시지에 포함하세요.
등록 불가 또는 버전 불일치만으로
degraded가 된 경우에도 메시지는0 lifecycle run(s) and 0 action(s)만 표시합니다. 운영자가 실제 저하 원인을 확인할 수 있도록unavailableRegistrations.length와versionMismatchCount를 메시지에 포함하세요.수정 예시
- message: `${runsByStatus.failed} lifecycle run(s) and ${failedActionCount} action(s) need attention`, + message: + `${runsByStatus.failed} lifecycle run(s), ${failedActionCount} action(s), ` + + `${unavailableRegistrations.length} unavailable registration(s), and ` + + `${versionMismatchCount} version mismatch(es) need attention`,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/lifecycle-core/src/libs/diagnostics/LifecycleDiagnosticsProvider.ts` around lines 136 - 150, Update the degraded status message in LifecycleDiagnosticsProvider to include unavailableRegistrations.length and versionMismatchCount alongside the existing failed run and action counts, so every cause contributing to degraded status is reported.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleVersionConflictProblem.md`:
- Line 8: 각 Problem 문서의 설명을 구체적인 오류 의미로 수정하세요.
packages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleVersionConflictProblem.md:8-8은
stale optimistic revision conflict,
packages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleVersionDefinitionProblem.md:8-8은
불변 version 정의 검증 실패,
packages/docs/src/content/docs/api/lifecycle-core/src/classes/UnavailableLifecycleRuleVersionProblem.md:8-8은
executable registration 부재,
packages/docs/src/content/docs/api/lifecycle-core/src/classes/UnknownLifecycleRuleVersionProblem.md:8-8은
등록되지 않은 rule version을 설명하도록 각각 변경하세요.
In `@packages/lifecycle-core/README.md`:
- Around line 81-84: Update the executableFingerprint value in the registration
example to pass an empty string when RULE_BUNDLE_SHA256 is missing, rather than
propagating undefined. Preserve the environment variable when present so
registerVersion() can return the intended executableFingerprint validation
problem.
In `@packages/lifecycle-core/src/libs/InMemoryLifecycleRuleStateStore.ts`:
- Around line 74-76: In InMemoryLifecycleRuleStateStore, add TTL-based pruning
for expired entries in the commands map, invoked at the start of every
applyCommand call. Follow the existing InMemoryIdempotencyStore.replay
pruneExpired pattern, preserving command replay behavior for unexpired entries
while removing stale command results.
In `@packages/lifecycle-core/src/libs/LifecycleRuleEvaluator.ts`:
- Around line 246-252: LifecycleRuleEvaluator의 idempotency key 해석 흐름에서
resolveIdempotencyKey(registration, input.context)의 예외를 redaction 경계 안에서 처리하도록
변경하세요. registration.rule.idempotencyKey가 실패하면 raw 예외를 전파하지 말고 안정적인 redacted
dry-run Problem으로 변환한 뒤 해당 결과가 저장되도록 하며, 정상적인 idempotency key와
resolveSuppression 흐름은 유지하세요.
In `@packages/lifecycle-core/src/libs/LifecycleRuleRegistry.ts`:
- Around line 265-276: add a focused test for registerVersion that re-registers
the same version on the same registry instance, then issues an activation
request and verifies the request is reflected correctly. Keep existing tests
unchanged and cover the immutable-version reuse path shown by the
existingRegistration handling.
In `@packages/lifecycle-core/src/libs/types.ts`:
- Around line 331-337: Update the LifecycleDryRunStore contract in
LifecycleDryRunStore so save and list use the same sync/async result union type
as LifecycleRuleStateStoreResult<T>, allowing both void or Promise<void> and
readonly LifecycleDryRunResult[] or its Promise form. Update
LifecycleRuleEvaluator and LifecycleDiagnosticsProvider callers to await these
operations while preserving their existing behavior.
- Around line 119-128: Update the changeset for `@croco/lifecycle-core` to include
the required non-patch version bump for making ruleVersion and ruleFingerprint
mandatory in LifecycleRun and LifecycleActionAdapter.run. Keep the
rule_unavailable union addition unchanged, and ensure the breaking type-contract
changes are released together.
In `@packages/lifecycle-core/src/tests/LifecycleRuleVersioning.spec.ts`:
- Around line 231-245: Update the concurrent pause assertions around
registry.pause so they do not assume the first Promise.allSettled result
succeeds. Assert that exactly one operation is fulfilled and the other is
rejected with LifecycleRuleVersionConflictProblem, following the assertion
pattern used in the nearby test around lines 281-306.
---
Outside diff comments:
In
`@packages/lifecycle-core/src/libs/diagnostics/LifecycleDiagnosticsProvider.ts`:
- Around line 136-150: Update the degraded status message in
LifecycleDiagnosticsProvider to include unavailableRegistrations.length and
versionMismatchCount alongside the existing failed run and action counts, so
every cause contributing to degraded status is reported.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: c96f6aed-84ac-46c1-a17b-83a5b0e49fb7
⛔ Files ignored due to path filters (1)
packages/problems-core/src/generated/problem-code-registry.tsis excluded by!**/generated/**
📒 Files selected for processing (60)
.changeset/versioned-lifecycle-rule-control.mddocs/problem-code-registry.jsonpackages/admin-ops/src/tests/RetryConsole.spec.tspackages/docs/src/content/docs/api/lifecycle-core/src/classes/InMemoryLifecycleActionSink.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/InMemoryLifecycleDryRunStore.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/InMemoryLifecycleRuleStateStore.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleActionContractProblem.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleCommandConflictProblem.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleEvaluator.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleRegistry.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleTransitionProblem.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleVersionConflictProblem.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/LifecycleRuleVersionDefinitionProblem.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/UnavailableLifecycleRuleVersionProblem.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/UnknownLifecycleRuleVersionProblem.mdpackages/docs/src/content/docs/api/lifecycle-core/src/classes/WebhookLifecycleActionAdapter.mdpackages/docs/src/content/docs/api/lifecycle-core/src/interfaces/LifecycleActionAdapter.mdpackages/docs/src/content/docs/api/lifecycle-core/src/interfaces/LifecycleDryRunStore.mdpackages/docs/src/content/docs/api/lifecycle-core/src/interfaces/LifecycleRuleStateStore.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleConditionEvidence.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleDryRunInput.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleDryRunProblem.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleDryRunResult.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleDryRunSignalEvidence.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleDryRunSuppression.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRule.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleActionDescriptor.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleActivationCommand.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleActivationCommandType.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleActivationEvent.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleEvaluatorOptions.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleIdentityState.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleInspection.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleRegistration.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleRegistrationInput.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleRegistryOptions.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleState.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleStateMutation.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleStateStoreResult.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleVersionDescriptor.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRuleVersionRecord.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleRun.mdpackages/docs/src/content/docs/api/lifecycle-core/src/type-aliases/LifecycleSkipReason.mdpackages/docs/src/content/docs/api/problems-core/src/classes/Problem.mdpackages/docs/src/content/docs/api/problems-core/src/variables/CROCO_PROBLEM_CODE_REGISTRY.mdpackages/docs/src/content/docs/en/reference/problem-recovery-cookbook.mdpackages/lifecycle-core/README.mdpackages/lifecycle-core/src/index.tspackages/lifecycle-core/src/libs/InMemoryLifecycleActionSink.tspackages/lifecycle-core/src/libs/InMemoryLifecycleDryRunStore.tspackages/lifecycle-core/src/libs/InMemoryLifecycleRuleStateStore.tspackages/lifecycle-core/src/libs/LifecycleRuleEvaluator.tspackages/lifecycle-core/src/libs/LifecycleRuleRegistry.tspackages/lifecycle-core/src/libs/WebhookLifecycleActionAdapter.tspackages/lifecycle-core/src/libs/diagnostics/LifecycleDiagnosticsProvider.tspackages/lifecycle-core/src/libs/problems/LifecycleProblems.tspackages/lifecycle-core/src/libs/types.tspackages/lifecycle-core/src/tests/LifecycleCore.spec.tspackages/lifecycle-core/src/tests/LifecycleRuleVersioning.spec.tspublic-api-surface.snapshot.json
b7a7c12 to
bd062d9
Compare
Outcome
Lifecycle rules now have stable identities, immutable version descriptors, explicit build-artifact fingerprints, and audited activate, pause, resume, and supersede transitions. Optimistic revisions and idempotent command IDs prevent silent replacement and concurrent state races, while asynchronous state-store contracts support durable atomic persistence.
Production runs and action emissions record the exact rule version and fingerprint. Dispatch rechecks authoritative state after awaited evaluation work, so a concurrent pause prevents new actions while retaining a skipped run. Existing register, get, getAll, and match calls remain synchronous through a documented local compatibility view.
Dry runs evaluate an explicit context without dispatching, saving a production run, or consuming cooldown. Results expose only safe signal identity, boolean condition evidence, declared action descriptors, suppression decisions, and redacted Problems. Diagnostics report active, paused, unavailable, dry-run, and version-mismatch evidence.
Fixes #1546
Verification
Review gates
Residual risk
Custom durable state stores must implement applyCommand as one atomic compare-and-swap transaction that also records command idempotency and activation history. Build pipelines must derive executableFingerprint from the deployed rule bundle and captured configuration. The synchronous compatibility view is intentionally not authoritative across processes; versioned execution and operations use the asynchronous store-backed APIs.
Summary by CodeRabbit
새 기능
문서