Documentation
Validation Library Integration Requirements
This document defines the mandatory integration requirements for all rules compilers to ensure consistent security validation across the codebase.
Enforcement Strategy
1. CI/CD Enforcement
All compilers must pass integration tests that verify they're using the validation library:
# .github/workflows/validation-compliance.yml
name: Validation Compliance
on: [push, pull_request]
jobs:
typescript-compliance:
runs-on: ubuntu-latest
steps:
- name: Check TypeScript uses validation library
run: |
cd src/rules-compiler-typescript
# Verify WASM module is imported
grep -q "adguard_validation" package.json || exit 1
grep -q "validate_local_file\|validate_remote_url" src/**/*.ts || exit 1
dotnet-compliance:
runs-on: ubuntu-latest
steps:
- name: Check .NET uses validation library
run: |
cd src/rules-compiler-dotnet
# Verify native library is referenced
grep -q "adguard_validation" src/**/*.csproj || exit 1
grep -rq "ValidationLibrary\|P/Invoke" src/ || exit 1
# Similar checks for Python and Rust compilers
2. Runtime Verification
Each compiler must implement a --validate-integration flag that verifies the validation library is properly integrated:
# All compilers must support this
npm run compile -- --validate-integration
dotnet run --project RulesCompiler.Console -- --validate-integration
rules-compiler --validate-integration
cargo run --release -- --validate-integration
This flag should:
- Attempt to load the validation library
- Run a simple validation test
- Exit with code 0 if successful, 1 if failed
3. Compilation Hook
All compilers must call validation library functions at these points:
Required Integration Points
Before Compilation:
// TypeScript example (all compilers must have equivalent)
import { Validator, ValidationConfig, VerificationMode } from '@adguard/validation';
async function compile(config: CompilerConfig): Promise<CompilerResult> {
const validator = new Validator(ValidationConfig.default());
// 1. MANDATORY: Validate all local input files
for (const localFile of getLocalInputFiles()) {
const result = await validator.validate_local_file(localFile);
if (!result.is_valid) {
throw new CompilationError(`Invalid input file: ${localFile}`);
}
}
// 2. MANDATORY: Validate all remote URLs
for (const url of getRemoteUrls()) {
const result = await validator.validate_remote_url(url, getExpectedHash(url));
if (!result.is_valid) {
throw new CompilationError(`Invalid remote URL: ${url}`);
}
}
// 3. Proceed with compilation using @adguard/hostlist-compiler
const output = await hostlistCompiler.compile(config);
// 4. MANDATORY: Handle file conflicts
const finalPath = await resolveConflict(output.path, config.conflictStrategy);
// 5. MANDATORY: Create archive if enabled
if (config.archiving.enabled) {
await createArchive(inputDir, archiveDir, output.hash, output.ruleCount);
}
return output;
}
4. Test Requirements
Each compiler must have integration tests that verify:
Test 1: Local File Validation
// Test that compilation fails if local file has invalid syntax
test('rejects invalid local file', async () => {
const invalidFile = 'test-data/invalid-syntax.txt';
await expect(compile(configWithFile(invalidFile))).rejects.toThrow();
});
Test 2: Hash Verification
// Test that compilation detects tampered files
test('detects file tampering via hash', async () => {
// First compile creates hash
await compile(config);
// Modify file
modifyFile('data/input/rules.txt');
// Second compile should detect tampering
await expect(compile(configWithStrictMode)).rejects.toThrow(/hash mismatch/i);
});
Test 3: URL Security
// Test that HTTP URLs are rejected
test('rejects insecure HTTP URLs', async () => {
const httpUrl = 'http://insecure.example.com/list.txt';
await expect(compile(configWithUrl(httpUrl))).rejects.toThrow(/HTTPS/i);
});
Test 4: Archive Creation
// Test that archives are created when enabled
test('creates archive when enabled', async () => {
const config = { ...baseConfig, archiving: { enabled: true } };
await compile(config);
expect(fs.existsSync('data/archive')).toBe(true);
const archives = fs.readdirSync('data/archive');
expect(archives.length).toBeGreaterThan(0);
});
5. Configuration Validation
All compilers must validate that configuration includes validation settings:
function validateConfig(config: CompilerConfig): void {
// MANDATORY: hashVerification section must exist
if (!config.hashVerification) {
throw new Error('Missing hashVerification configuration');
}
// MANDATORY: Must specify verification mode
if (!['strict', 'warning', 'disabled'].includes(config.hashVerification.mode)) {
throw new Error('Invalid hashVerification.mode');
}
// Additional validation...
}
6. Dependency Declaration
Each compiler's dependency file must declare the validation library:
TypeScript (package.json):
{
"dependencies": {
"@adguard/validation": "file:../adguard-validation/pkg"
}
}
.NET (csproj):
<ItemGroup>
<NativeLibraryReference Include="adguard_validation" />
</ItemGroup>
Python (requirements.txt):
adguard-validation>=1.0.0
Rust (Cargo.toml):
[dependencies]
adguard-validation = { path = "../adguard-validation/adguard-validation-core" }
7. Pre-commit Hooks
A pre-commit hook verifies validation library integration:
#!/bin/bash
# .git/hooks/pre-commit
echo "Checking validation library integration..."
# Check TypeScript
if ! grep -q "adguard_validation" src/rules-compiler-typescript/package.json; then
echo "ERROR: TypeScript compiler missing validation library dependency"
exit 1
fi
# Check .NET
if ! grep -q "adguard_validation" src/rules-compiler-dotnet/src/**/*.csproj; then
echo "ERROR: .NET compiler missing validation library reference"
exit 1
fi
# Similar checks for Python and Rust
echo "✓ All compilers properly integrated with validation library"
8. Documentation Requirements
Each compiler's README must include:
- Integration Status section showing validation library usage
- Security Features section listing which validations are performed
- Configuration section documenting validation settings
- Code examples showing validation in action
9. Pull Request Template
PR template includes validation library checklist:
## Validation Library Integration
- [ ] Uses validation library for file validation
- [ ] Uses validation library for URL security
- [ ] Implements hash verification
- [ ] Creates archives when enabled
- [ ] Handles file conflicts
- [ ] Integration tests pass
- [ ] Documentation updated
10. Breaking Changes Policy
Any PR that bypasses the validation library is automatically rejected.
Exceptions require:
- Written justification
- Security team approval
- Alternative security measures documented
- Temporary exemption with deadline
Verification Commands
Maintainers can verify compliance with:
# Run compliance check across all compilers
./tools/check-validation-compliance.sh
# Expected output:
# ✓ TypeScript: Validation library integrated
# ✓ .NET: Validation library integrated
# ✓ Python: Validation library integrated
# ✓ Rust: Validation library integrated
# ✓ All integration tests passing
Penalties for Non-Compliance
- CI fails - PR cannot be merged
- Code review rejection - Automatic "Request Changes"
- Security alert - Flagged in security dashboard
- Rollback - Non-compliant code reverted if merged
Migration Timeline
- Phase 1 (Current): Validation library created, documented
- Phase 2 (Next): Integrate into TypeScript compiler (reference implementation)
- Phase 3: Integrate into .NET, Python, Rust compilers
- Phase 4: Enable CI enforcement (warnings only)
- Phase 5: Enable CI enforcement (blocking)
- Phase 6: Remove legacy validation code
Support
Questions about integration? See:
src/adguard-validation/README.md- Full integration guidedocs/validation-integration-guide.md- Step-by-step tutorial- GitHub Discussions - Ask the community