Merged
Conversation
- SanitizerEngine with idempotent sanitize pipeline - AttributeSanitizer: #[Sanitize] attribute-driven field sanitization - SanitizationContextImpl: immutable fluent builder (readonly) - 33 built-in rules across String, Html, Numeric, Type, Date, Filter, Brazilian - SanitizerConfiguration with trackSanitizations, allowNullOverwrite - Integration: ProcessorBridge for reactive pipeline compatibility
- 86 tests: AttributeSanitizer, SanitizerEngine, all 33 rule classes - Conformance: ImmutableStateTest, ArchitecturalContractTest - PHPUnit 12 compatible attribute-based annotations
- SanitizerServiceProvider: replace 'use ...\String' with 12 individual class imports (String is a reserved PHP class name) - HtmlRulesTest: fix testStripTagsWithAllowed expected value PHP strip_tags() preserves text nodes inside stripped tags: '<b>hello</b><script>x</script>' with allowed='<b>' → '<b>hello</b>x' - Apply psalm --alter #[Override] on all interface implementations - Rename QualityDirectiveV40Test → ArchitecturalContractTest All changes verified: kcode test passes (86 tests, no failures)
- Adds kariricode/property-inspector v2.0.0 from Packagist to require block - Provides PropertyInspector, AttributeAnalyzer, and PropertyAccessor - Enables reflection metadata caching per class (no re-inspection on repeated calls) - Replaces zero-dependency design with a single dependency on the framework's canonical attribute-inspection library
- New SanitizeAttributeHandler: implements PropertyAttributeHandler + PropertyChangeApplier; collects #[Sanitize] rules per property - AttributeSanitizer: replaces raw ReflectionClass loop with PropertyInspector::inspect() + SanitizeAttributeHandler - PropertyAccessor used for writing sanitized values back to objects - Gains reflection metadata cache from AttributeAnalyzer kcode test: 86 tests, 0 failures
…isting test classes Refactor all 8 pre-existing test files to comply with ARFA 1.43 V4.0 and PHPUnit 12+ standards: - Add #[Test] attribute to every test method - Add #[CoversClass] (or #[CoversNothing] for conformance/integration tests) - Split omnibus testGetName() into individual granular test methods - Use assertSame with literal string constants for rule name assertions - Ensure declare(strict_types=1) in all test files Affects: AttributeSanitizerTest, SanitizerServiceProviderTest, InMemoryRuleRegistryTest, SanitizationContextImplTest, SanitizerEngineTest, ArchitecturalContractTest, ImmutableStateTest, FullRuleRegistrationTest
Refactor 7 rule test files to comply with PHPUnit 12 and ARFA standards: - Add #[Test] attribute to every test method - Add #[CoversClass] for each rule class under test - Split testGetName() into individual testXxxRuleName() methods (one assertSame per method, using literal string constants) - declare(strict_types=1) verified in all files Covers: BrazilianRulesTest, DateRulesTest, FilterRulesTest, HtmlRulesTest, NumericRulesTest, StringRulesTest, TypeRulesTest
…rt types Create 5 new test files covering previously untested production classes: - SanitizationResultTest: FieldModification, SanitizationResult (merge, count, get) - SanitizeAttributeHandlerTest: handleAttribute, merge, non-Sanitize passthrough, setProcessedValues, applyChanges, ReflectionException-catch branch (7 methods) - SanitizationEventsTest: SanitizationStartedEvent, SanitizationCompletedEvent with all constructor paths including default timestamps - SanitizationExceptionsTest: InvalidRuleException + SanitizationException factory methods with and without previous Throwable - ProcessorBridgeTest: process() with sanitized output and empty-data path Brings class coverage from 87.50% to 100% (48/48 classes)
…arameter() pattern
Replace (string)/(int)/(bool) casts on mixed getParameter() return values
with explicit is_string/is_int/is_bool narrowing to satisfy PHPStan level 9.
Pattern applied consistently across all 11 String rules:
Before: $max = (int) $context->getParameter('max', 255);
After: $maxRaw = $context->getParameter('max', 255);
$max = is_int($maxRaw) ? $maxRaw : 255;
Specific rules fixed:
- TrimRule: characters parameter
- PadRule: length (int), pad (string), side (string)
- RegexReplaceRule: pattern (string), replacement (string)
- ReplaceRule: search/replace — simplified to is_string guard with early return
- SlugRule: separator parameter
- TruncateRule: max (int), suffix (string)
- CapitalizeRule, LowerCaseRule, UpperCaseRule, NormalizeWhitespaceRule,
NormalizeLineEndingsRule, StripNonPrintableRule: cs-fixer style fixes only
Resolves PHPStan cast.string and cast.int errors in String rule namespace
…ameter() pattern Apply the same type-narrowing idiom to all 5 Html rules to eliminate PHPStan missingType.cast.string / cast.int errors at level 9: - HtmlDecodeRule: flags (int), encoding (string) - HtmlEncodeRule: flags (int), encoding (string), double_encode (bool) - HtmlPurifyRule: allowed (string) - StripTagsRule: allowed (string) - UrlEncodeRule: raw (bool) Uses explicit is_int / is_string / is_bool narrowing before using the parameter value, with typed defaults as fallback
…, Date, Filter, Type and Brazilian rules
Numeric:
- RoundRule: extract 10**precision into $multiplier, cast to (float)
to resolve Psalm InvalidOperand in strict binary operands mode
- ClampRule, ToIntRule, ToFloatRule: cs-fixer Yoda-style comparisons
Date:
- NormalizeDateRule: from/to narrowed from mixed to string
- TimestampToDateRule: format/timezone narrowed from mixed to string;
timezone additionally validated as non-empty-string to satisfy
Psalm ArgumentTypeCoercion for DateTimeZone::__construct
Filter:
- EmailFilterRule: add @psalm-suppress RedundantCast to resolve
PHPStan/Psalm disagreement on filter_var FILTER_SANITIZE_EMAIL
- AlphaOnlyRule, AlphanumericOnlyRule, DigitsOnlyRule: cs-fixer style
Type / Brazilian:
- ToBoolRule, ToStringRule, ToArrayRule: cs-fixer style
- FormatCepRule, FormatCnpjRule, FormatCpfRule: Yoda comparisons
…salm errors
SanitizeAttributeHandler:
- Typed $fieldRules property from list<mixed> to the full union matching
SanitizerEngine::sanitize() signature to fix AttributeSanitizer argument.type
- Updated getFieldRules() return type PHPDoc accordingly
SanitizerEngine:
- Added @param array<string, mixed> to resolveValue() private method
- Added @param union type annotation to resolveRule() parameter $definition
- Added @return array{0: SanitizationRule, 1: array<string, mixed>} to resolveRule
Sanitize (Attribute):
- Added @param PHPDoc to variadic __construct parameter
- Added intermediate @var typed local to satisfy assign.propertyType
(PHPStan cannot infer list<string|array{...}> from variadic spread)
AttributeSanitizer:
- Resolved argument.type mismatch via improved SanitizeAttributeHandler types
ProcessorBridge:
- Added SanitizationRule import
- Added full typed union @param/@var annotations matching engine signature
- Resolves missingType.iterableValue and argument.type errors
Apply PHP CS Fixer Yoda-style comparison rule across all support
infrastructure classes that were not touched by previous type-safety commits:
Before: $x === null → After: null === $x
Before: $x !== '' → After: '' !== $x
Files: RuleRegistry, SanitizationContext, SanitizationRule contracts,
SanitizerConfiguration, SanitizationCompletedEvent, SanitizationStartedEvent,
InvalidRuleException, SanitizationException, FieldModification,
SanitizationResult, InMemoryRuleRegistry, SanitizationContextImpl,
SanitizerServiceProvider
No logic changes — pure cs-fixer style conformance
- Remove root-level .php-cs-fixer.php (config now lives at .kcode/php-cs-fixer.php, managed by kariricode/devkit) - Update README.md to reflect current public API, coverage badge, and ARFA 1.43 V4.0 compliance status No functional changes to production code or tests
Document key design decisions for the sanitizer: - ADR-001: Rule Registry Pattern — alias-based InMemoryRuleRegistry - ADR-002: Property Inspector Integration — kariricode/property-inspector replaces raw Reflection API for attribute scanning - ADR-003: Sanitization Context Immutability — final readonly SanitizationContextImpl - ADR-004: ARFA 1.43 Rule Passthrough Contract — non-matching types returned unchanged - ADR-005: Zero-Dependency Rule Implementation — all 33 rules use PHP built-ins only Also adds docs/README.md index linking all ADRs and SPECs.
Library projects have no runtime environment requirements. .env is already gitignored; .env.example is misleading and unnecessary.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.