Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cilician Bundle Laravel Package

jgxvx/cilician-bundle

Cilician Bundle integrates the Cilician PHP library with Symfony, providing bundle registration, dependency-injection wiring, and configuration so Cilician services can be installed and used in Symfony applications with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

First, confront the framework mismatch. This is a Symfony bundle (Bundle class + Symfony DI service definitions), not a Laravel package. In a Laravel app you cannot composer require it and have it boot. "Getting started" therefore means one of two things:

  • Symfony shop: register the bundle in config/bundles.php (or rely on auto-discovery if the version supports it), then look first at the DependencyInjection/ extension and the client class — that is where the API key header, base URL, and User-Agent are wired. Publish/override config only for the API key and timeout.
  • Laravel shop (the expected case): treat it as a reference implementation, not a dependency. Read the small source to learn the endpoint paths, header requirements, and status-code semantics, confirm the licence (not stated in metadata — check before copying anything), and reimplement ~100–200 lines natively.

Where to look first, in order:

  1. The client class — endpoint methods and how they map to HIBP v3 (breachedAccount, pasteAccount, breaches, breach/{name}, dataClasses, latestBreach).
  2. The DI extension — config keys, defaults, and how the API key is injected.
  3. Status handling — confirm whether 404 is treated as "not breached" rather than an error, and whether 429 backoff exists.

First use case — the one to ship first: the Pwned Passwords range API (k-anonymity SHA-1, first 5 hash chars only). It is free, needs no paid key, sends no PII, and blocks breached passwords at signup/reset. That is the lowest-risk, highest-visibility win and it defers every privacy-review question.

Minimal Laravel equivalent to stand up instead:

// config/services.php
'hibp' => [
    'key'        => env('HIBP_KEY'),
    'user_agent' => env('HIBP_USER_AGENT', 'MyApp/1.0'),
    'base_url'   => 'https://haveibeenpwned.com/api/v3',
    'timeout'    => 5,
],

Bind a BreachCheck interface in a service provider, back it with Http::withHeaders([...])->timeout(...), and keep controllers unaware of HIBP.

Implementation Patterns

1. Wrap, never call directly. Define an internal interface (PasswordBreachCheck, EmailBreachLookup) and bind an implementation in a service provider. Whether you vendored the bundle's client or wrote your own, the auth path depends on your interface. This is the whole return on reading the package: the request semantics, not the object graph.

2. Password check at the boundary — always fail-open.

public function isPwned(string $password): bool
{
    $sha1   = strtoupper(sha1($password));
    $prefix = substr($sha1, 0, 5);
    $suffix = substr($sha1, 5);

    $body = Cache::remember("hibp:range:$prefix", now()->addDay(), fn () =>
        Http::timeout(2)
            ->withHeaders(['User-Agent' => config('services.hibp.user_agent')])
            ->get("https://api.pwnedpasswords.com/range/$prefix")
            ->throw()
            ->body()
    );

    foreach (explode("\n", $body) as $line) {
        [$hash, $count] = explode(':', trim($line));
        if ($hash === $suffix) {
            return true; // optionally return (int) $count for telemetry
        }
    }
    return false;
}

Call it in a FormRequest rule or a dedicated BlockBreachedPasswords action at signup and reset. If the call times out or errors, let the signup through — an HIBP outage must never block registration or login.

3. Email lookup — queue it, never inline. The breached-account endpoint requires a paid key, sends user email addresses to a third party, and is rate-limited (~1.5 req/sec). Put it in a job:

final class CheckEmailForBreaches implements ShouldQueue
{
    public function handle(BreachLookup $hibp, EventDispatcher $events): void
    {
        $breaches = $hibp->breachedAccount($this->email);

        if ($breaches !== []) {
            $events->dispatch(new EmailBreachDetected($this->user, $breaches));
        }
    }
}

Consumers of EmailBreachDetected: forced password reset, session revocation, MFA step-up, risk scoring.

4. Cache the catalogue, rate-limit the lookups. Breach metadata (breaches, breach/{name}, dataClasses) is near-static — cache for hours. Wrap lookups in a Laravel RateLimiter keyed to HIBP's limit so a burst of queued jobs doesn't trip 429. Caching also shrinks the blast radius of an upstream outage.

5. Fake it in tests and CI. Bind a fake BreachLookup implementation in the test container. Keep recorded HIBP fixtures for contract tests so no API key is needed in the pipeline and behaviour on 404/401/429 is asserted, not assumed.

6. Emit domain events, not UI side effects. The service answers "is this breached?"; queues, notifications, and auth policy react to the event. That keeps the HIBP client swappable and the fail-open policy in one place.

Gotchas and Tips

Framework fit is the first gotcha. Do not attempt to install this into Laravel. Symfony's container does not consume Laravel's, and pulling Symfony components into an auth path for a thin REST wrapper buys nothing. Read it, reimplement it.

404 means "not breached", not "error." The single most common bug in HIBP integrations is treating a 404 from breachedAccount as a failure — which either throws on every clean account or, worse, silently marks every user as breached. Handle it explicitly. Conversely, 401 (missing/invalid key) and 429 (rate limit) are real errors and should surface to your monitoring.

The User-Agent header is mandatory. HIBP rejects requests without it. Make it a config constant, not an afterthought — and never derive it from user input.

The API key is a paid requirement for everything except passwords. Budget for it (~$3.95/month), know it is billed to the account, and respect the terms: no bulk enumeration, no reselling. The free range API is the only exception.

Never call HIBP synchronously on a hot path. Signup, login, and reset are latency- and availability-sensitive. Short timeouts, a circuit breaker, and a fail-open default are non-negotiable. If you check passwords at volume, self-host the Pwned Passwords range dataset or front it with a long-TTL cache — the dataset is free and immutable enough.

PII in logs is a real leak. The breached-account endpoint sends email addresses; ensure neither the package (if you vendor it) nor your client logs request bodies, emails, or key material on error. Audit the error paths, not just the happy path.

Supply-chain posture. Zero stars, zero dependents, single maintainer, Codeberg-hosted, no visible CI or advisory channel, and no stated licence. For anything touching credentials:

  • Confirm the licence before reusing code — even small snippets.
  • If you must depend on it, pin a commit and vendored-fork it; do not track a branch.
  • Assume no upstream patch cadence. When HIBP changes headers or status semantics, you are the maintainer.

Extension points are thin on purpose. There is no meaningful algorithm, schema, or storage layer to inherit — the value is endpoint/header/status knowledge. That makes it easy to replace and hard to justify depending on.

Config quirks: defaults tend to be override-friendly, so publish/override only the key, timeout, and base URL. Keep the key in .env, out of version control, and remember that a framework config cache means a changed key needs a cache clear.

Scope discipline: ship the password check first (free, hashed-only, no DPA/DPIA work). Treat email-based lookup and any domain-wide monitoring as a separate roadmap decision with a recurring vendor cost and a privacy review attached — not a config flag.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource