Use aindot/extra-rules Laravel validation rules (IBAN, IMEI, ISBN, national IDs, barcodes, etc.), magic guess, and sample generation. Use when adding form/request validation, guessing identifier types, or generating test fixtures for specialty formats.
php artisan boost:add-skill aindot/extra-rules
Save this content to: .claude/skills/extra-rules-development/SKILL.md
# Extra Rules (aindot/extra-rules)
Laravel `ValidationRule` classes for real-world identifiers (national IDs, barcodes, telecom, finance, media). Prefer these over ad-hoc regex when a matching rule exists.
## Install & messages
```bash
composer require aindot/extra-rules
php artisan vendor:publish --tag=extra-rules-translations
```
English and Arabic messages ship under `extra-rules::validation.*`. Locale: `app()->setLocale('ar')`.
## Validation usage
Rules live in `Aindot\ExtraRules\Rules\*` and implement `Illuminate\Contracts\Validation\ValidationRule`.
```php
use Aindot\ExtraRules\Rules\Iban;
use Aindot\ExtraRules\Rules\KuwaitCivilId;
use Illuminate\Support\Facades\Validator;
Validator::make($data, [
'civil_id' => ['required', new KuwaitCivilId],
'iban' => ['required', new Iban],
]);
```
Same pattern in Form Requests: `new \Aindot\ExtraRules\Rules\Isbn13`.
## Rule catalog (RuleType value → class)
Use `Aindot\ExtraRules\RuleType` string values (snake_case) or enum cases. Classes: `Aindot\ExtraRules\Rules\{Name}`.
| Area | Keys |
|------|------|
| National IDs | `kuwait_civil_id`, `emirates_id`, `iqama`, `egyptian_nid`, `cpf`, `cnpj`, `ssn`, `passport_mrz` |
| Books/media | `isbn10`, `isbn13`, `issn`, `isni`, `iswc`, `istc`, `isan`, `ismn`, `isrc`, `doi`, `nbn`, `urn` |
| Barcodes/trade | `ean8`, `ean13`, `upc_a`, `upc_e`, `gtin8`, `gtin13`, `gtin14`, `itf14`, `sscc` |
| Telecom/device | `imei`, `imeisv`, `imsi`, `iccid`, `meid`, `esn`, `mac_address`, `e164` |
| Finance | `iban`, `bic`, `credit_card`, `cvv` |
| Other | `email`, `uuid`, `ulid`, `jwt`, `hex_color`, `slug`, `vin` |
| Secrets | `private_key`, `api_key`, `bearer_token` |
Aliases accepted by `RuleType::fromMixed()` include: `swift`→`bic`, `phone`→`e164`, `mrz`→`passport_mrz`, `kuwait_id`→`kuwait_civil_id`, `uae_id`→`emirates_id`.
## Magic guess
```php
use Aindot\ExtraRules\ExtraRules;
use Aindot\ExtraRules\Facades\ExtraRules as ExtraRulesFacade;
use Aindot\ExtraRules\RuleType;
$matches = (new ExtraRules)->magic($value); // list<RuleType>
$matches = ExtraRulesFacade::magic($value, ['credit_card', RuleType::Imei]);
```
```bash
php artisan extra-rules:magic "4111111111111111"
php artisan extra-rules:magic "4111111111111111" --rules=credit_card,imei
```
Values starting with `-` are parsed as options; separate them with `--`:
```bash
php artisan extra-rules:magic --rules=private_key -- "$(cat id_openssh)"
```
Do not pass secrets as CLI arguments: they appear in shell history and `ps`, and a
misparsed value can end up in `storage/logs/laravel.log`. Prefer the in-code call
(`(new ExtraRules)->magic($key)`), which uses no argv parsing.
## Redact secrets
```php
use Aindot\ExtraRules\ExtraRules;
use Aindot\ExtraRules\RuleType;
$clean = (new ExtraRules)->redact($text);
$findings = (new ExtraRules)->detect($text); // [['type' => RuleType, 'offset' => int, 'length' => int], ...]
$clean = (new ExtraRules)->redact($text, ['iban', RuleType::CreditCard]);
```
Supported types: `iban`, `api_key`, `bearer_token`, `jwt`, `kuwait_civil_id`, `credit_card`, `private_key`.
Matches are replaced with `[REDACTED:<type>]`; overlaps keep the longest match (`Bearer <jwt>` → one `bearer_token`).
`detect()` never returns secret values.
```bash
php artisan extra-rules:redact --file=log.txt
cat log.txt | php artisan extra-rules:redact --stdin
php artisan extra-rules:redact "card 4111111111111111"
php artisan extra-rules:redact --file=log.txt --types=iban,credit_card
php artisan extra-rules:redact --file=log.txt --list
```
Prefer `--file`/`--stdin` for secret-bearing input. A 13-digit EAN/ISBN can pass Luhn and be reported as `credit_card`.
## Generate valid samples
```php
$imei = (new ExtraRules)->generate('imei');
$ibans = (new ExtraRules)->generateMany(RuleType::Iban, 5);
```
```bash
php artisan extra-rules:generate imei
php artisan extra-rules:generate iban --count=5
```
Use generators for tests/fixtures so values pass the same checksum rules as production validation.
## Package conventions (contributing)
- New rule: `src/Rules/FooBar.php` implementing `ValidationRule`, use `RejectsInvalidValue` + `extra-rules::validation.*` keys.
- Register in `RuleType` enum (`case`, `ruleClass()`, aliases if needed) and `Generator` for sample output.
- Add Pest unit tests with real-world valid/invalid examples (checksum-aware, not only format).
- Translations: `resources/lang/{en,ar}/validation.php` (and commands if CLI text changes).
Laravel ValidationRule classes for real-world identifiers (national IDs, barcodes, telecom, finance, media). Prefer these over ad-hoc regex when a matching rule exists.
composer require aindot/extra-rules
php artisan vendor:publish --tag=extra-rules-translations
English and Arabic messages ship under extra-rules::validation.*. Locale: app()->setLocale('ar').
Rules live in Aindot\ExtraRules\Rules\* and implement Illuminate\Contracts\Validation\ValidationRule.
use Aindot\ExtraRules\Rules\Iban;
use Aindot\ExtraRules\Rules\KuwaitCivilId;
use Illuminate\Support\Facades\Validator;
Validator::make($data, [
'civil_id' => ['required', new KuwaitCivilId],
'iban' => ['required', new Iban],
]);
Same pattern in Form Requests: new \Aindot\ExtraRules\Rules\Isbn13.
Use Aindot\ExtraRules\RuleType string values (snake_case) or enum cases. Classes: Aindot\ExtraRules\Rules\{Name}.
| Area | Keys |
|---|---|
| National IDs | kuwait_civil_id, emirates_id, iqama, egyptian_nid, cpf, cnpj, ssn, passport_mrz |
| Books/media | isbn10, isbn13, issn, isni, iswc, istc, isan, ismn, isrc, doi, nbn, urn |
| Barcodes/trade | ean8, ean13, upc_a, upc_e, gtin8, gtin13, gtin14, itf14, sscc |
| Telecom/device | imei, imeisv, imsi, iccid, meid, esn, mac_address, e164 |
| Finance | iban, bic, credit_card, cvv |
| Other | email, uuid, ulid, jwt, hex_color, slug, vin |
| Secrets | private_key, api_key, bearer_token |
Aliases accepted by RuleType::fromMixed() include: swift→bic, phone→e164, mrz→passport_mrz, kuwait_id→kuwait_civil_id, uae_id→emirates_id.
use Aindot\ExtraRules\ExtraRules;
use Aindot\ExtraRules\Facades\ExtraRules as ExtraRulesFacade;
use Aindot\ExtraRules\RuleType;
$matches = (new ExtraRules)->magic($value); // list<RuleType>
$matches = ExtraRulesFacade::magic($value, ['credit_card', RuleType::Imei]);
php artisan extra-rules:magic "4111111111111111"
php artisan extra-rules:magic "4111111111111111" --rules=credit_card,imei
Values starting with - are parsed as options; separate them with --:
php artisan extra-rules:magic --rules=private_key -- "$(cat id_openssh)"
Do not pass secrets as CLI arguments: they appear in shell history and ps, and a
misparsed value can end up in storage/logs/laravel.log. Prefer the in-code call
((new ExtraRules)->magic($key)), which uses no argv parsing.
use Aindot\ExtraRules\ExtraRules;
use Aindot\ExtraRules\RuleType;
$clean = (new ExtraRules)->redact($text);
$findings = (new ExtraRules)->detect($text); // [['type' => RuleType, 'offset' => int, 'length' => int], ...]
$clean = (new ExtraRules)->redact($text, ['iban', RuleType::CreditCard]);
Supported types: iban, api_key, bearer_token, jwt, kuwait_civil_id, credit_card, private_key.
Matches are replaced with [REDACTED:<type>]; overlaps keep the longest match (Bearer <jwt> → one bearer_token).
detect() never returns secret values.
php artisan extra-rules:redact --file=log.txt
cat log.txt | php artisan extra-rules:redact --stdin
php artisan extra-rules:redact "card 4111111111111111"
php artisan extra-rules:redact --file=log.txt --types=iban,credit_card
php artisan extra-rules:redact --file=log.txt --list
Prefer --file/--stdin for secret-bearing input. A 13-digit EAN/ISBN can pass Luhn and be reported as credit_card.
$imei = (new ExtraRules)->generate('imei');
$ibans = (new ExtraRules)->generateMany(RuleType::Iban, 5);
php artisan extra-rules:generate imei
php artisan extra-rules:generate iban --count=5
Use generators for tests/fixtures so values pass the same checksum rules as production validation.
src/Rules/FooBar.php implementing ValidationRule, use RejectsInvalidValue + extra-rules::validation.* keys.RuleType enum (case, ruleClass(), aliases if needed) and Generator for sample output.resources/lang/{en,ar}/validation.php (and commands if CLI text changes).How can I help you explore Laravel packages today?