Skip to content

docs: record why the deployed demo can't be shared as-is (#32) - #26

Open
Newtdev wants to merge 1 commit into
mainfrom
docs/multi-tenancy-analysis
Open

Newtdev wants to merge 1 commit into
mainfrom
docs/multi-tenancy-analysis

Conversation

@Newtdev

@Newtdev Newtdev commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Documents the multi-tenancy analysis before any code is written. Status: Proposed — nothing here is built, and the hosting question is deliberately left open.

Why now

The demo backend, landing page and mobile app already form a complete working loop (verified end to end against production today — 23 checks). That invites an obvious shortcut: let a developer install the mobile SDK, point it at this deployment, share links on this domain, and skip hosting a backend entirely.

Mechanically that works on the first try. That's what makes it worth writing down before anyone tries it.

Finding 1 — nothing knows which app a click belongs to

No app_id, tenant_id, bundle_id or client_id in either backend's schema. The concept doesn't exist. And /match filters on exactly two predicates:

gte(referralClicks.createdAt, windowStart)
gt(referralClicks.expiresAt, new Date())

A window and an expiry. Every recent click is a candidate for every device; the winner is decided purely on fingerprint score.

The default weights show how big that is. The five non-recency signals — ip_match 25, device_model 25, screen_dimensions 15, timezone 10, language 10 — sum to 85, against a min_confidence of 70. Two users of two different apps sharing a carrier NAT, on the same handset model, in the same locale, score 85 before recency is considered at all.

Where carrier NAT is normal and a few handset models dominate, that isn't an edge case — it's the expected outcome. Developer B's user receives Developer A's referral code, and the conversion is recorded against it. Wrong attribution, with a reward budget attached.

Unreachable today because exactly one app uses the deployment. Reachable the day a second one does.

Finding 2 — the landing page serves one app

appScheme and store URLs are deployment config, not per-link data. Every demo link deep-links to myapp://. A second developer's links would route their users into the first developer's app.

Why the click token can't fix it

Recorded because it's the natural first idea. The token is outbound. It's minted server-side at /click and at a successful /match; /match accepts no token at all, so it cannot constrain the candidate query — which is exactly where Finding 1 lives.

Binding app_id into the payload does work at /claim, and is worth doing. But that's defence in depth, not the identification mechanism. What's needed is an inbound public app id on every call.

Scope, in two blocks

Correctness — required before a second app touches the deployment: app_id through link → click → match in both backends, /match filtering on it, an apps registry so the landing page stops being single-app, app_id bound into the claim token. ~a week, doubled for parity.

Product — only if hosting becomes an offering: key issuance, signed webhook or verify endpoint for reward distribution, a registration surface.

Relationship to #31

A general hosted service contradicts #31. A shared sandbox doesn't, if described honestly — best-effort, rate-limited, short retention, no SLA, production self-hosted. One coherent story: self-host for production, sandbox to try it.

The operational line

Do not share the deployment before the correctness block lands. Until then a second app on it produces silent cross-app mis-attribution — the one category of bug this project can't ship, since every other guarantee rests on attributing the right click to the right install.

The demo backend, landing page and mobile app already form a working loop,
which invites an obvious shortcut: let developers install the mobile SDK,
point it at this deployment, share links on this domain, and skip hosting
a backend entirely. Mechanically that works on the first try, which is
exactly what makes it worth writing down before anyone tries it.

Two findings. Neither schema has any notion of which app a click belongs
to — no app_id, tenant_id, bundle_id or client_id in either backend — and
/match's candidate query filters only on the match window and expiry, so
every recent click is a candidate for every device. With the default
weights the five non-recency signals sum to 85 against a threshold of 70,
so two users of two different apps behind the same carrier NAT on the same
handset model in the same locale cross-match before recency is even
considered. Second, appScheme and the store URLs are deployment config
rather than per-link data, so one deployment can only ever route to one
app.

Also records why the existing click token can't fix this, since it's the
natural first idea: the token is outbound. It's minted server-side at
/click and at a successful /match, and /match accepts no token at all, so
it cannot constrain the candidate query. Binding app_id into the payload
does work at /claim and is worth doing, but as defence in depth rather
than as the identification mechanism.

Scoped in two blocks, because they differ in kind: the correctness work
required before a second app touches the deployment, and the product work
only warranted if hosting becomes an offering. Records the tension with
#31 and the sandbox framing that resolves it, and states outright that the
deployment must not be shared before the correctness block lands.

Status Proposed — nothing here is built and the hosting question is open.
@vercel

vercel Bot commented Sep 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
referral-sdk-node Ready Ready Preview Sep 15, 2026 9:42pm UTC
referral-web-demo Ready Ready Preview Sep 15, 2026 9:42pm UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant