FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Original HTTPS Page]

malikad778 (Adnan Haider) 路 GitHub

馃挱
Coding Solutions
馃挱
Coding Solutions

Highlights

  • Pro

Block or report malikad778

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Close all issues, pull requests, and discussions opened by this user Content in all repositories owned by your account will be closed.
Add an optional note
Maximum 250 characters. Please don鈥檛 include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user鈥檚 behavior. Learn more about reporting abuse.

Report abuse
malikad778/readme.md

Backend Engineer 聽路聽 Laravel 聽路聽 PHP 8.3 聽路聽 Multi鈥憈enant SaaS

Six years of PHP, most of it on the unglamorous half. The queue that has to drain. The webhook that cannot return a 502. The migration that would have taken a table lock at 4pm on a Friday.

I write the boring, load鈥慴earing code, and the static analysis that keeps other people from breaking it.


Proposal SaaS

Turning a delivered single鈥憈enant product into a real multi鈥憈enant one

I shipped this for one client: GrapesJS canvas, a ~900鈥憀ine server renderer, headless鈥慍hrome PDF export, cryptographic sealing, in鈥慴rowser signature capture. It works. Now I am pulling the single鈥憈enant assumptions out of it one at a time, which is turning out to be harder than building it was.

The editor was never the hard part. Tenancy is. Every B2B leak postmortem I have read comes down to the same thing: someone treated isolation as a query filter instead of a boundary the query cannot escape.

flowchart TD
    C["Company<br/><i>tenant 路 billing entity</i>"]
    T["Team<br/><i>grouping inside a company</i>"]
    U["User<br/><i>1 company 路 0..n teams</i>"]
    R1["Owner 路 Admin 路 Member"]
    R2["team_admin 路 member"]

    C -->|"SECURITY BOUNDARY<br/>never removed"| T
    T -->|"VISIBILITY FILTER<br/>layered on top"| U
    U -.company role.-> R1
    U -.team role.-> R2

    classDef sec fill:#132E5C,stroke:#1F6FEB,stroke-width:2px,color:#F0F6FC
    classDef vis fill:#2A1B4D,stroke:#8957E5,stroke-width:2px,color:#F0F6FC
    classDef ent fill:#161B22,stroke:#30363D,color:#C9D1D9
    classDef role fill:#0D1117,stroke:#21262D,color:#8B949E
    class C sec
    class T vis
    class U ent
    class R1,R2 role
Loading

Important

CompanyScope applies no filter at all when no tenant resolves. That sounds like the bug. It is deliberate, so console commands and migrations still work, and it is safe for exactly one reason: users.company_id is NOT NULL. An authenticated user can never resolve to null and see everything. Make that column nullable and the whole design becomes a data leak.

Five invariants I defend with tests, not comments

Invariant What breaks without it
Scope narrows, never swaps Team visibility built by replacing the company scope instead of layering on it. This is the classic leak.
Fails open, deliberately Console commands and migrations stop working. Safe only while users.company_id stays NOT NULL.
Roles are per company Spatie's team_foreign_key points at company_id. Point it at teams.id and roles leak across tenants.
Authorisation self鈥憇copes User::can() binds to the user's own company. Otherwise every check inside a job or command silently returns false.
Two locale axes users.locale is the sender's UI. proposals.locale is the signed document. A German agency sends an English proposal to a UK buyer.

This one already bit me twice, in defaultTeam() and again in provisionRoles():

- // Looks harmless. Returns an empty collection when another tenant is current,
- // which produces users with no team and no visibility. No error, no warning.
- $company->teams()->get();

+ // Team carries CompanyScope, so any walk of a company's children has to run
+ // inside that company's context, even when you already hold the model.
+ CompanyContext::for($company->id, fn () => $company->teams()->get());

The actual phase tracker(where this sits today)

Phase 1 is not done until an isolation suite proves Company A cannot reach Company B's proposals, templates, settings, media, smart content, email templates, users or teams through any route. Nothing downstream starts before that gate passes.

  • 1a Tenancy schema migrations
  • 1b Models, BelongsToCompany, visibility scopes, factories
  • 1c Global鈥憇ingleton fixes (cache keys, unique constraints)
  • 1d Roles, permissions, policies
  • 1i Internationalisation, dual鈥慳xis 聽code done, ~110 admin strings left
  • 1e Public sign鈥憉p, registration links, invitations 聽in progress
  • 1f Per鈥憈enant credentials plus SSRF guard
  • 1g Cross鈥憈enant isolation suite 聽Phase 1 gate
  • 1.5 Decoupling from the upstream billing system
  • 2 Billing, plan limits, reminders
  • 3 Approvals and multi鈥憇igner

Debt I have written down rather than pretended away: the PDF endpoint regenerates with headless Chrome on every download. Sealed proposals are immutable, so that is pure waste, and it becomes the dominant hosting cost the moment a free tier exists. It gets cached before launch, not after.

Translation policy: formatting works for all 25 locales, but reviewed strings ship for en and de only. A proposal is a quasi鈥憀egal document somebody signs. A mistranslated accept, decline or expiry clause is a dispute, not a typo, so machine translation does not go near the client鈥慺acing axis.


Meta Lead Ads to WhatsApp

Webhook ingestion that does not drop leads

Meta does not care about your queue depth. Return slowly enough, often enough, and it marks the endpoint unhealthy and throttles the campaign. So nothing does real work on the request thread.

sequenceDiagram
    autonumber
    participant M as Meta Lead Ads
    participant W as Webhook endpoint
    participant D as MySQL
    participant Q as Redis 路 Supervisor
    participant A as WhatsApp Cloud API

    M->>W: POST lead payload
    W->>W: verify X-Hub-Signature-256<br/>via hash_equals()
    W->>D: INSERT (unique meta_leadgen_id)
    Note over D: replay collides here,<br/>not in application code
    W-->>M: 200 in milliseconds
    W->>Q: dispatch job
    Q->>A: send templated message
    A--xQ: 5xx or rate limit
    Q->>Q: exponential backoff, time-bounded
    Q->>A: retry
    A-->>Q: delivered
Loading

Two integrity gates, deliberately independent. The signature check rejects forgeries. The unique index on meta_leadgen_id makes a replay a no鈥憃p at the database level. I want the second one in the schema rather than in a service class, because schemas do not get refactored around at 2am.

Backoff is time鈥慴ounded, not attempt鈥慴ounded. A provider outage should degrade throughput and then recover. It should not silently exhaust retries and drop a lead somebody paid for.


Solo founder. My architecture, my pager.

Log a decision, revisit it on a schedule, find out whether your instincts actually calibrate. Backed by Google Cloud for Startups and MongoDB for Startups.

Building it alone taught me more about cost than about code. Embeddings are cheap to call and expensive to call badly, and the difference is entirely in what you cache.


Open source

Eight packages, 83 stars, all PHP. Each one exists because I hit the problem on a real project, went looking for the fix, and did not find one that worked properly.

Stock sync for Laravel across Shopify, WooCommerce, Amazon and Etsy. The easy part is the webhooks. The real part is what happens when two channels sell the last unit inside the same second.

Laravel 10-12 聽Webhooks 聽Job queues

Watches the JSON a third party actually sends you and infers its shape over time. When a field quietly disappears or changes type, you hear about it from this instead of from a customer.

PHP 8.3+ 聽Schema drift 聽MIT

Reads your migrations in CI and fails the build on the ones that take a table lock or drop a column with data behind it. Zero config. Rails has strong_migrations; Laravel did not.

AST parser 聽CI gate 聽Zero config

Orphaned listeners, unheard hooks, misspelled action names. Finds all three by reading source, without ever bootstrapping WordPress, so it is fast enough to run on every commit.

PHP CLI 聽WordPress 聽Static analysis

Multi鈥慶hannel dispatch for Laravel 12. When a provider starts timing out the breaker trips and reroutes, instead of parking twenty workers on a dead endpoint until the queue backs up.

Laravel 12 聽Circuit breaker 聽Telemetry

73 WCAG 2.1 AA rules for Blade and Livewire, aimed at the European Accessibility Act. Ships a baseline file, because a linter that turns a legacy codebase red on day one just gets switched off.

WCAG 2.1 AA 聽Baseline 聽CI

Makes a WordPress site readable by AI agents. Semantic chunking, FAQ extraction, media and author indexing, llms.txt and an MCP manifest, all over REST.

MCP 聽WordPress 聽REST

Gates OTP before the user row is written, so bots never create the account at all. Includes SMS pumping and AIT fraud defence, which is the bill most OTP plugins leave you to find out about.

WooCommerce 聽Fraud defence 聽Multisite


Stack

CORE
DATA
INFRA
FRONT
APIS
TEST

The code itself

The install count is the number I actually watch. Stars are a bookmark; an install means somebody put the package in a composer.json and let it run in their build.

Language split across the eight packages, by source bytes

PHP 87.1% 聽路聽 Blade 6.6% 聽路聽 JavaScript 3.5% 聽路聽 CSS and HTML 2.8%

Measured across the eight packages, not every repo on the account. Counting everything puts JavaScript on top at 33.6%, which is just my portfolio site's vendored assets talking. The number that means something is the one over code other people run in their own CI.


How I work

A test that never disagrees with you is decoration. Write the one that fails when the invariant breaks, not the one that passes today. In a multi鈥憈enant system the tests worth having are the ones that go red the second somebody collapses two axes into one.

Fail loudly at the boundary, gracefully in the middle. Reject a malformed payload at ingestion, where it is cheap and you still have the context. The alternative is a half鈥憌ritten row three services deep that a customer finds for you next week.

Write down the deviation and the reason. Plans are wrong in places. Six months later the useful artefact is not the plan, it is knowing why the code went the other way and what would have to change for the original idea to work.

Comments explain why. Code explains what. If a block needs a comment to say what it does, rewrite the block. Save the comments for the constraints you cannot see from the syntax, like a port collision that presents as an auth error.


Laravel 路 PHP 路 multi鈥憈enant SaaS 路 integration鈥慼eavy systems

Based in Pakistan, working remotely.

adnanhaider0347@gmail.com 聽路聽 codebyadnan.tech 聽路聽 LinkedIn

Pinned Loading

  1. notification-center notification-center Public

    Enterprise-grade multi-channel notification engine for Laravel 12 with parallel dispatching, smart routing, and real-time monitoring

    PHP 8 1

  2. Laravel-migration-guard Laravel-migration-guard Public

    Catch dangerous Laravel migrations before they reach production. Static analysis, zero config. The strong_migrations equivalent for Laravel.

    PHP 18

  3. php-sentinel php-sentinel Public

    Passive API Contract Monitoring for PHP 8.3+. Detects breaking changes, json schema drift, and unexpected structural modifications in third-party REST APIs via probabilistic inference.

    PHP 18

  4. nexus-inventory nexus-inventory Public

    The ultimate Laravel package for multi-channel inventory synchronization. Connect Shopify, WooCommerce, Amazon, and Etsy to Laravel with real-time webhooks, job queues, and a unified API.

    PHP 29 6

  5. wp-hook-check wp-hook-check Public

    Static analysis for WordPress hooks. Detect orphaned listeners, unheard hooks, and typos in actions and filters without running WordPress. Faster, safer WP development.

    PHP 10

  6. blade-access blade-access Public

    Static accessibility analyzer for Laravel Blade & Livewire - 73 WCAG 2.1 AA rules, CI integration, baseline system, zero runtime dependency.

    PHP


Back | FazBrowse Home | New Git URL