From rendr-forge-skills
Reconnaissance pass over an unfamiliar or vibe-coded codebase that produces SURFACE.md, an inventory of data models, every entry point, where data lives, the tenant model, third-party services, and where money moves. Use at the very start of a deslop / security audit / takeover, whenever you need to understand an inherited or AI-generated app before changing it, or when the user asks "what does this app actually do / expose". Run before plug-the-holes and launch-gate; they both consume SURFACE.md.
How this skill is triggered — by the user, by Claude, or both
Slash command
/rendr-forge-skills:map-the-surfaceThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build the map before you walk the territory. **You cannot audit a surface you haven't mapped**, and generated codebases reliably hide entry points the author no longer remembers: a debug route, a webhook from a half-finished payments experiment, a second database from when they switched ORMs mid-vibe.
Build the map before you walk the territory. You cannot audit a surface you haven't mapped, and generated codebases reliably hide entry points the author no longer remembers: a debug route, a webhook from a half-finished payments experiment, a second database from when they switched ORMs mid-vibe.
The output is one artifact: SURFACE.md. It feeds /plug-the-holes (what to attack) and /launch-gate (what to verify). Keep it factual; this is reconnaissance, not judgement. Findings come later.
See ../deslop/GLOSSARY.md for Surface, Tenant isolation, and the other terms used here.
Speak the project's language. If the repo already has a CONTEXT.md (the domain glossary used by the architecture/grilling skills), read it first and name things in SURFACE.md using its terms ("the Order intake function", not "the FooHandler"). If the codebase is vibe-coded and has no CONTEXT.md, and recon forces you to coin a durable name for a core concept (the tenant, a central module), write that term into CONTEXT.md (create it lazily) rather than inventing a private synonym. That keeps recon, the audit, and Phase 2 all speaking one domain vocabulary; see the "Vocabulary layers" note in the glossary.
Read the README, package.json/manifest, and any config. Answer in one paragraph: what does this app do, for whom, and who are its tenants (orgs? users? both?). If you can't answer "who is a tenant", that gap is itself the first thing to flag. Multi-tenancy you can't describe is multi-tenancy you can't isolate.
Explore the codebase (use a subagent to explore if available). Don't grade anything yet. Capture six things:
orgId, userId, accountId…). Note any model with no tenant key; that's a future Hole waiting.STACK.md names as your surface unit; mark which are meant to be internal-only).env, dashboard, hardcoded?). Don't print secret values into SURFACE.md; record locations only.Structure it so the audit can be driven straight off it. Tables over prose — every row is one auditable thing.
# SURFACE — <app name>
Generated YYYY-MM-DD by /map-the-surface. Inventory, no grading.
## App
| Field | Value |
|----------|------------------------------------------------------------------|
| Purpose | <one line: what the app does, for whom> |
| Users | <e.g. operator / supervisor / client> |
| Tenant | <e.g. organisation, keyed by `organisationId` on every domain row>|
| Stage | <pre-launch / private beta / live with paying users> |
## Data models
| Model | Tenant key | PII? | Notes |
|-------|------------|------|-------|
<one row per table/collection/schema. Models WITHOUT a tenant key are pre-flagged in Notes.>
## Entry points (the surface)
| Entry point | Type | Auth expected? | Tenant-scoped? | Money? | Notes |
|-------------|------|----------------|----------------|--------|-------|
<one row per route / public function / webhook / upload / consumer / queue/cron consumer / client-callable backend function>
## Data stores
| Store | Purpose | Backed up? | Notes |
|-------|---------|------------|-------|
## Third-party services
| Service | Used for | Key location | Costs per call? |
|---------|----------|--------------|-----------------|
## Money & identity flows
- Authn: <where / how>
- Authz: <where it's meant to live>
- Charging / entitlement paths: <list>
## Unknowns
- <anything you couldn't determine — resolved by /plug-the-holes, not guessed>
The "Auth expected?" / "Tenant-scoped?" columns are deliberately claims to test, not facts; /plug-the-holes turns each suspicious row into an exploit test (or, where infeasible, a documented code-inspection finding). An honest Unknowns section is worth more than confident guesses. A vibe-coded app will have unknowns, and pretending otherwise is how Holes survive the audit.
SURFACE.md done → proceed to /plug-the-holes. If recon surfaced something obviously catastrophic (a literal API key in the client bundle, an admin route with no auth), note it as Suspected and carry it straight into the audit. Don't fix mid-recon, you'll lose the map.
Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub rendr-web/rendr-forge-skills --plugin rendr-forge-skills