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

Built For Cloud Laravel Package

artisan-build/built-for-cloud

A Laravel package that helps you build cloud-ready applications by auditing common deployment pitfalls and guiding configuration for stateless, scalable hosting. Artisan commands surface issues with local storage, sessions, and caches so your app runs smoothly across containers and multiple servers.

View on GitHub
Deep Wiki
Context7

Getting Started

This release is the first usable cut of the device-authorization feature, so treat it as the entry point rather than an add-on.

  1. Publish and migrate first. The lifecycle is persisted (start records, serialized single exchange, expiry/prune), so publish config + migrations and run php artisan migrate before touching routes. Nothing in the flow works against an unmigrated database.
  2. Read the HTTP contract docs shipped in PR B before writing client code. They are the authoritative description of POST /bfc/device-authorizations, GET|POST /bfc/device, POST /bfc/device/token, GET|POST /bfc/loopback/authorize, POST /bfc/loopback/token. Write your client against the contract, not against the scripted clients.
  3. Look at the shipped approval views and scripted clients. The Blade approval screens show what the human sees and which fields are safe to render; the scripted clients are working reference implementations of polling cadence, PKCE, and error handling.
  4. Register the prune command in your scheduler in the same PR that adopts the feature. Authorizations accumulate; expiry without pruning is not cleanup.

First use case: an installer or CLI that needs a purpose-scoped credential. The CLI calls POST /bfc/device-authorizations, prints the verification URL and user code, polls POST /bfc/device/token at the advertised cadence, and on success holds a bearer credential bound to the approving subject. Do this end-to-end against a local approval view before wiring your real command.

Implementation Patterns

Choose the flow by topology, not by preference.

  • Device code — CLI, headless installer, remote shell, anything where the browser is on a different machine. Human approves in a browser; the CLI polls.
  • Loopback + PKCE — desktop/native app where the browser and the client are on the same host. Requires an exact loopback callback (no wildcard ports, no prefix matching) plus a PKCE verifier you keep server-side or in memory for the duration of the flow.

Model purposes explicitly. Request the narrowest purpose the caller needs and keep the profile/purpose policy in config. An installer credential should not become your runtime API credential. Withdrawal of a kind or profile is terminal — design your credential storage so a terminal denial is a "re-provision from scratch" path, not a refresh path.

Respect the cadence contract. Poll on the interval the start response gives you, back off on slow-down responses, and stop on expiry. Do not implement polling as a tight retry loop with your own interval; the server-side cadence is part of the protocol.

Serialise the exchange. Exactly one token exchange per authorization is permitted. In queue workers or multi-process CLIs, guard the exchange (lock keyed on the authorization, or a single owning process) — two workers racing the same authorization is a self-inflicted denial.

Wire the bearer check into host resolution. The credential's bound subject must equal the host's resolved request subject. Put subject resolution behind one service your auth middleware and the package both use, so the comparison has a single definition. Test it through your real middleware stack, not just the controller.

Integrate via the approval views and clients. Override the shipped approval views for branding/copy, but keep the decision payload shape intact. Use the scripted clients as test fixtures: run them against a fake HTTP layer to assert your cadence and terminal-denial handling.

Testing patterns that pay off:

  • Http::fake() the contract endpoints; assert the sequence start → poll → token, including the "slow down" and "expired" branches.
  • Freeze time (travel) for cadence windows and expiry boundaries.
  • Assert that your DTO/response layer never emits the start object's internal fields (see gotchas).
  • Assert a subject-mismatch bearer is rejected — this is the security-relevant case and the easiest to leave uncovered.

Scheduling: prune on a schedule tighter than your expiry window, and alert if prune stops running; an unpruned table is both a growth and a stale-authorization problem.

Gotchas and Tips

DeviceAuthorizationStart is not a public payload. It carries an internal id and a reveal-once nonce. Do not toArray()/toJson()/log it, and do not return it verbatim from your own controller or console output. Map it to your own DTO at the boundary — this is disclosed in the release notes, so assume it will be checked in review.

The denial-reason vocabulary is not database-enforced. The closed set exists in code but not as a DB constraint. If you persist or branch on denial reasons, validate against the vocabulary in your own layer and add a test that an unexpected value fails loudly rather than silently falling through a match.

Denial can be connection-wide. Containment rules mean a denial can terminate other in-flight authorizations on the same connection. Do not model a denial as isolated to one request; have a path that clears cached pending state for the connection/tenant.

Terminal vs retryable is the whole error model. Kind/profile withdrawal is terminal. Expiry is terminal. Cadence violations are recoverable. Retrying a terminal denial turns a clear failure into an opaque one, and with single-exchange semantics a naive retry on the token endpoint can burn the authorization.

Exact-bound bearer means proxy sensitivity. Anything that changes the resolved request subject — load balancer headers, trusted-proxy config, host normalisation — can turn valid credentials into denials. Verify behind the same proxy config you run in production, not just artisan serve.

Loopback URIs are exact. http://127.0.0.1:PORT/cb and http://localhost:PORT/cb are different registrations, and a random ephemeral port needs a matching registration strategy. Decide this before you ship the desktop client.

Clock skew affects both cadence floor and expiry. Keep hosts NTP-synced; a fast client clock looks like cadence abuse.

Extension points: purpose/profile policy config, the approval views, and the scripted clients. Prefer these over subclassing the lifecycle internals — the internals (nonce, serialized exchange) are the parts the release notes explicitly mark as not-for-consumption.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib