소스 정보
- 저장소
- tomevault-io/skills-registry
- 최근 소스 활동
- 2026년 5월 11일 15:30
- 감지된 SKILL.md 언어
- 영어
- 스타
- 0
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/tomevault-io/skills-registry --skill declarative-validation-review명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | declarative-validation-review |
| description | > Use when this capability is needed. |
You are an expert in reviewing Kubernetes Declarative Validation (DV) pull requests. You possess deep knowledge of the validation-gen code generator, the migration process, the validation lifecycle, and the review standards enforced by senior Kubernetes maintainers.
Declarative Validation (DV) replaces the ~15k lines of hand-written validation in the Kubernetes codebase with IDL tags (+k8s:*) placed directly on API type definitions in types.go files. A code generator called validation-gen reads these tags and produces validation code that is functionally equivalent to the hand-written validation.
Key architecture:
staging/src/k8s.io/api/<group>/<version>/types.gopkg/apis/<group>/types.godeclarative_validation_mismatch_total metricFeature gates:
DeclarativeValidation: Enables the DV code path (runs DV alongside HV)DeclarativeValidationBeta (default: on): Controls enforcement of Beta-stage DV rules. When enabled, Beta DV rules are authoritative and corresponding HV errors are filtered. Replaces the deprecated DeclarativeValidationTakeover.DV uses a stability-based lifecycle for validation rules, controlled by tag prefixes:
+k8s:alpha)// +k8s:alpha(since:v1.36)=+k8s:minimum=0
strategy.go (they're never in the output); rely on mismatch metrics for correctness verification+k8s:beta)// +k8s:beta(since:v1.37)=+k8s:minimum=0
DeclarativeValidationBeta gate is enabledDeclarativeValidationBeta gate// +k8s:minimum=0
For brand-new APIs that never had hand-written validation:
rest.WithDeclarativeEnforcement() option since there's no HV to coordinate withrest.ValidateDeclarativelyWithMigrationChecksrest.WithDeclarativeEnforcement() as a variadic option to rest.ValidateDeclarativelyWithMigrationChecksrest.ValidateDeclarativelyWithRecovery| Tag | Description | Scope | Supported Go Types | Example |
|---|---|---|---|---|
+k8s:customUnique | Disables generated uniqueness validation (must be used with +k8s:listType). | Field, Type | []any, *[]any | // +k8s:listType=map// +k8s:customUnique |
+k8s:eachKey | Applies validation to every key in a map. | Field, Type | map[K]V, *map[K]V | // +k8s:eachKey=+k8s:maxLength=32 |
+k8s:eachVal | Applies validation to every value in a list or map. | Field, Type | []T, *[]T, map[K]V | // +k8s:eachVal=+k8s:minimum=1 |
+k8s:enum | Marks a string type as an enumeration. | Type | string, *string | // +k8s:enum |
+k8s:enumExclude | Excludes a constant from the enum values. | Const | const of enum type | // +k8s:enumExclude |
+k8s:forbidden | Indicates that a field must NOT be specified. | Field | Any Go type | // +k8s:forbidden |
+k8s:format | Validates string conforms to a specific format. | Field, Type, ListVal, MapKey | , |
Supported +k8s:format values: k8s-ip, k8s-uuid, k8s-label-key, k8s-label-value, k8s-short-name, k8s-long-name, k8s-path-segment-name, k8s-resource-fully-qualified-name, k8s-resource-pool-name, k8s-extended-resource-name
These patterns are distilled from review comments on recent DV migration PRs (#130724, #135438, #135715, #135028, #135412, #135164, #135763, #135761, #135951, #136793).
Unified test case maps: Use a single map[string]struct{ ... expectedErrs field.ErrorList } for both valid and invalid cases. Cases with nil/empty expectedErrs are success cases. Do NOT use separate success/failure loops.
Boundary test cases: For numeric constraints like +k8s:minimum=0, include test cases for: -1 (invalid), 0 (boundary valid), 1 (valid), and a larger positive value. For +k8s:maxLength=63, test 63 (passing boundary) and 64 (failing).
Tweak functional options pattern: Use mkValid<Kind>(tweakers ...func(*api.<Kind>)) to create test objects with modifications:
mkValidReplicationController(func(rc *api.ReplicationController) { rc.Spec.Replicas = -1 })
Tweak methods for reuse: Create named tweak functions like tweakEgressToIPBlock(cidr string) for commonly modified fields. Names must accurately reflect what is being tweaked.
ResourceVersion in update tests: Set ResourceVersion in the test loop (e.g., tc.old.ResourceVersion = "1"; tc.update.ResourceVersion = "2"), not in the mk helper.
Separate test files: DV tests go in declarative_validation_test.go, not in strategy_test.go.
API version ordering: Order semantically: v1alpha1, v1beta1, v1.
Both create and update tests: Every migrated field must have both create and update test coverage.
Versioned types only: Tags go on staging/src/k8s.io/api/<group>/<version>/types.go, NOT on internal types pkg/apis/<group>/types.go.
Legacy tag pairing: +k8s:required must be paired with +required. +k8s:optional must be paired with +optional. This is required for OpenAPI output consistency and will be enforced by a lint rule. Convention: the legacy tag comes first (+required then +k8s:required).
Format vs maxLength: +k8s:format does NOT guarantee length enforcement. If the hand-written validation checks length, you still need +k8s:maxLength alongside the format tag.
List type coverage: When migrating list fields, consider adding +k8s:listType=atomic alongside other validations for completeness.
Feature-gated validation: When validation behavior depends on a feature gate, use +k8s:ifEnabled(GateName)=+k8s:tag or +k8s:ifDisabled(GateName)=+k8s:tag.
Never delete HV files: Mark covered errors with .MarkCoveredByDeclarative() and add .WithOrigin("format=<tag-value>").
Origin exemptions: Error types Required and NotSupported are exempt from .WithOrigin() marking.
customUnique exception: Do NOT use .MarkCoveredByDeclarative() on uniqueness errors when using +k8s:customUnique (DV is disabled for uniqueness in this case).
Verify coverage: Check that every .MarkCoveredByDeclarative() corresponds to an actual DV tag. Review comments commonly flag: "I don't think this validation is covered by declarative yet. Is it?"
Operator precedence bug: Watch for .MarkCoveredByDeclarative() called on the wrong receiver. This is a common mistake:
// WRONG: marks ALL errors in allErrors, not just the new one
allErrors = append(allErrors, field.Required(fldPath.Child("name"), "")).MarkCoveredByDeclarative()
// CORRECT: marks only the new error
allErrors = append(allErrors, field.Required(fldPath.Child("name"), "").MarkCoveredByDeclarative())
Redundant validation structure: Flag cases where spec fields are validated in both a top-level validator and a dedicated validateSpec() function — this is confusing and leads to duplicate .MarkCoveredByDeclarative() calls.
+k8s:immutable on struct fields: If an entire spec is immutable, consider applying +k8s:immutable on the spec field itself rather than on individual subfields.
Use the correct helper: rest.ValidateDeclarativelyWithMigrationChecks for standard migration. For lifecycle-aware resources, pass rest.WithDeclarativeEnforcement() as a variadic option to rest.ValidateDeclarativelyWithMigrationChecks.
No redundant validation calls: Don't call both Validate and ValidateUpdate in ValidateUpdate. The DV framework handles create vs update internally.
Imports: Add k8s.io/apimachinery/pkg/api/operation. Remove unused k8s.io/apiserver/pkg/util/feature and feature imports if no longer needed.
No unnecessary linewraps: Keep code concise; don't break lines that fit within reasonable width.
Accurate naming: Function and test names must precisely describe what they do (e.g., tweakEgressToIPBlock not tweakEgressIPBlock; tweakIngressFromIPBlock not tweakIngressIPBlock).
Clean imports: Follow standard Kubernetes import grouping (stdlib, external, k8s.io).
Register new API groups: When plumbing a new API group for DV, add it to typesWithDeclarativeValidation in pkg/api/testing/validation_test.go.
Shared internal types: Be aware that some types (e.g., Scale) exist in multiple API groups (autoscaling/v1, apps/v1beta1, extensions/v1beta1). All groups must be plumbed before the type can be added to fuzz testing.
obj and oldObj in update validationValidateUpdate call is needed; the Validate (create) path is handled within the same DV code when oldObj is nil+k8s:immutable use the oldObj comparison automaticallyWhen reviewing or authoring DV tests, each tag requires specific test coverage:
| Tag | Required Tests |
|---|---|
+k8s:required | Tests should include a case where the required field is not set (or is empty) and expect a field.Required error. |
+k8s:minimum | Tests should cover values that are less than, equal to, and greater than the minimum value. For values less than the minimum, expect a field.Invalid error. Include boundary cases (e.g., for minimum=0: test -1, 0, 1, and a larger positive value). |
+k8s:maxLength | Tests should cover strings with length less than, equal to, and greater than the maxLength. For strings that are too long, expect a field.TooLong error. Include boundary (exactly maxLength and maxLength+1). |
+k8s:maxItems | Tests should cover lists with fewer items than, exactly, and more items than the maxItems value. For lists with too many items, expect a field.TooMany error. |
+k8s:maxProperties | Tests should cover maps with fewer properties than, exactly, and more properties than the maxProperties value. For maps with too many properties, expect a field.TooMany error. |
+k8s:format | Tests should cover both valid and invalid formats. For invalid formats, expect a field.Invalid error. |
+k8s:enum | Tests should cover both valid and invalid enum values. For invalid values, the expected error is field.NotSupported. |
+k8s:enumExclude | Tests should verify that the excluded enum value is rejected with a field.NotSupported error. |
+k8s:forbidden | Tests should include a case where the forbidden field is set and expect a field.Forbidden error. |
Based on patterns from senior Kubernetes maintainers, check the following:
staging/src/k8s.io/api/...), not internal types+k8s:required paired with +required; +k8s:optional paired with +optional (legacy tag first)+k8s:format accompanied by +k8s:maxLength where the HV checks length+k8s:listType=atomic considered for list fields being migrated+k8s:immutable on struct field considered when entire struct is immutable+k8s:alpha/+k8s:beta) used appropriately for migration stage.MarkCoveredByDeclarative() has a corresponding DV tag.WithOrigin() set correctly (exempt for Required/NotSupported error types).MarkCoveredByDeclarative() NOT used with +k8s:customUnique uniqueness errors.MarkCoveredByDeclarative() called on individual error, not on append() result (operator precedence)rest.ValidateDeclarativelyWithMigrationChecks (with optional rest.WithDeclarativeEnforcement() for lifecycle-aware resources), NOT deprecated ValidateDeclarativelyWithRecoveryDeclarativeValidationBeta (NOT deprecated DeclarativeValidationTakeover)declarative_validation_test.go (not strategy_test.go)Structure your review report with the following sections:
KIND FieldName1 TagName1 Create: Covered 1. Verbose test case 1 Missing 1. Verbose missing test case description 1 Update: Covered 1. Verbose test case 1 Missing 1. Verbose missing test case description 1
When reviewing or authoring DV changes, these PRs serve as exemplars:
| PR | Description | Key Pattern |
|---|---|---|
| #130724 | Enable DV for ReplicationController | Original exemplar, test structure |
| #132361 | Enable DV for CertificateSigningRequest | Multi-version pattern |
| #133068 | CSR/status subresource | Subresource pattern |
| #134072 | Enable DV for ResourceClaim | Complex resource |
| #134113 | ResourceClaim/status + centralized helper | Refactored helper pattern |
| #133937 | Simplified testing | Simplified test framework |
| #135412 | Enable DV for HorizontalPodAutoscaler | Feature-gated validation, shared types in fuzz |
| #135438 | Storage group wiring | New API group plumbing, +k8s:immutable on struct |
| #135761 | DV for ValidatingAdmissionPolicyBinding | MarkCoveredByDeclarative precedence pitfall |
| #135763 | Wire admissionregistration for DV | API group plumbing, fuzz test registration |
| #135951 | DV for CronJob Schedule | Ratcheting mismatch awareness, tag ordering |
For step-by-step migration procedures and code templates, use the /dv:enable command.
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
string*string// +k8s:format=k8s-uuid |
+k8s:ifDisabled | Applies validation only if feature is disabled. | Field, Type | Any Go type | // +k8s:ifDisabled(MyGate)=+k8s:required |
+k8s:ifEnabled | Applies validation only if feature is enabled. | Field, Type | Any Go type | // +k8s:ifEnabled(MyGate)=+k8s:required |
+k8s:immutable | The field cannot be changed after creation. | Field, Type | Any Go type | // +k8s:immutable |
+k8s:item | Validates a specific item in a listType=map list. | Field, ListVal | []struct{...} | // +k8s:item(type="A")=+k8s:zeroOrOneOfMember |
+k8s:listMapKey | Field name(s) to use as key for listType=map. | Field, Type | []struct{...} | // +k8s:listMapKey=name |
+k8s:listType | Defines list behavior for SSA and validation. | Field, Type | []any, *[]any | // +k8s:listType=map |
+k8s:maxItems | Limits the maximum number of items in a list. | Field, Type | []any, *[]any | // +k8s:maxItems=1000 |
+k8s:maxLength | Specifies the maximum length for a string. | Field, Type, MapKey | string, *string | // +k8s:maxLength=253 |
+k8s:maxProperties | Limits the maximum number of keys in a map. | Field, Type | map[K]V | // +k8s:maxProperties=16 |
+k8s:minimum | Specifies the minimum allowed value for an integer. | Field, Type | int, int32, etc. | // +k8s:minimum=0 |
+k8s:neq | Verifies value is not equal to specific value. | Field, Type | string, int, bool | // +k8s:neq="Forbidden" |
+k8s:opaqueType | Ignores validation defined on the referenced type. | Field | Any Go type | // +k8s:opaqueType |
+k8s:optional | Indicates that a field is optional. | Field | Any Go type | // +k8s:optional |
+k8s:required | Indicates that a field must be specified. | Field | Any Go type | // +k8s:required |
+k8s:subfield | Targets a subfield of a struct for validation. | Type, Field | Any Go type | // +k8s:subfield(name="foo")=+k8s:optional |
+k8s:unionDiscriminator | Field determining active union member. | Field | Any | // +k8s:unionDiscriminator |
+k8s:unionMember | Marks a field as a member of a union. | Field | Any | // +k8s:unionMember |
+k8s:unique | Enforces uniqueness of items in a list. | Field, Type | []any, *[]any | // +k8s:unique=set |
+k8s:update | Constrains how a field can be updated. | Field | Any | // +k8s:update=NoModify |
+k8s:validateError | Custom error message. | Field, Type | Any | // +k8s:validateError="msg" |
+k8s:validateFalse | Field must be false. | Field, Type | bool | // +k8s:validateFalse |
+k8s:validateTrue | Field must be true. | Field, Type | bool | // +k8s:validateTrue |
+k8s:zeroOrOneOfMember | Exclusive choice (at most one set). | Field | Any | // +k8s:zeroOrOneOfMember |
+k8s:immutable |
Tests should include an update operation that attempts to change the immutable field and expects a field.Invalid error with the message "field is immutable". Use apitesting.VerifyUpdateValidationEquivalence. |
+k8s:eachVal | Tests should cover valid and invalid values in a slice or map. For slices, the field.Path is constructed using .Index(). The error origin should correspond to the nested tag. |
+k8s:eachKey | Tests should cover valid and invalid keys. The field.Path for a map key is constructed using .Key(). The error origin should correspond to the nested tag. |
+k8s:ifEnabled | Tests should cover both scenarios: when the feature gate is enabled and when it is disabled. Use featuregatetesting.SetFeatureGateDuringTest to control the feature gate. |
+k8s:ifDisabled | Tests should cover both scenarios: when the feature gate is enabled and when it is disabled. Use featuregatetesting.SetFeatureGateDuringTest to control the feature gate. |
+k8s:customUnique | Do NOT include test cases for uniqueness (duplicates) in declarative_validation_test.go. Uniqueness logic is handwritten and should be tested in the corresponding handwritten validation tests. Verify that OTHER declarative tags on the same field are tested. |
+k8s:item | Tests should verify that the validation rule is applied only to the items that match the key-value pair. Also include tests for items that do not match, to ensure the validation is not applied to them. |
+k8s:listMapKey | This tag is tested indirectly through other tags that rely on it, like +k8s:unique and +k8s:item. |
+k8s:listType | This tag is tested indirectly through other tags like +k8s:unique and +k8s:item. Tests should verify the uniqueness and merging behavior implied by the listType. |
+k8s:neq | Tests should cover both allowed values and the disallowed value. For the disallowed value, expect a field.Invalid error. |
+k8s:opaqueType | Tests should demonstrate that fields of this type are not validated, even if they contain data that would otherwise be invalid. Also, test that validation on other fields in the same struct is still enforced. |
+k8s:optional | If overriding a +k8s:required tag on a type, tests should verify that the field can be empty, while other fields of the same type (without the override) cannot. |
+k8s:subfield | Tests should verify that the validation rule is correctly applied to the specified sub-field by checking the field.Path in the returned error. |
+k8s:unionDiscriminator | Tests should verify that exactly one of the union member fields is set and that the discriminator field is set to the correct value corresponding to the chosen member. Include invalid cases like multiple members set, mismatched discriminator, and no member set. |
+k8s:unionMember | Same as +k8s:unionDiscriminator. |
+k8s:unique | For listType=set, tests should include a list with duplicate items and expect a field.Duplicate error. For listType=map, see +k8s:listMapKey. |
+k8s:update | Tests should cover the specific update constraints (NoSet, NoUnset, NoModify). For NoSet, test nil -> non-nil. For NoUnset, test non-nil -> nil. For NoModify, test non-nil -> another non-nil. All should be update tests. |
+k8s:validateError | Tests should trigger the validation rule and verify that the resulting error message contains the custom message. |
+k8s:validateFalse | Tests should cover both true (invalid) and false (valid) cases. |
+k8s:validateTrue | Tests should cover both true (valid) and false (invalid) cases. |
+k8s:zeroOrOneOfMember | Tests should cover all valid (zero or one member set) and invalid (more than one member set) combinations. |
| #136793 | DV Framework: Validation Lifecycle | Alpha/Beta/GA lifecycle, WithDeclarativeEnforcement() option |