Marcela Nunez
CEO and Co-founder
Mogi das Cruzes, Brazil
Actions
Marcela Nunez is a mechanical engineer (mechatronics, Mackenzie) with a specialization in project management from FGV. She co-founded PS Line Systems, a custom software studio in Brazil that builds with AI coding agents, where she leads requirements, system design and product for PS JUS, a SaaS for law firms. She is also the founder of Cela Cosméticos and a humor creator with 80k+ followers on Instagram, which means she spends a lot of time explaining technical things to people who aren't engineers.
Area of Expertise
You pasted the prod dump. Now find every copy.
Everyone in this room has pasted something they shouldn't have. A stack trace with a customer's email in it. A config file, to ask why the connection fails. A few rows of production data, because the bug only happens with real data. You did it because it was the fastest way to get an answer, and it worked.
The useful question is not whether that was careless. It's mechanical: **your agent has read access to everything and write access to your repository.** That is the shape of an exfiltration path, and it does not require anyone to be malicious. So let's trace it properly, in three parts, with a synthetic marker we can follow. I build a SaaS for law firms entirely with a coding agent, where a leak is professional secrecy, so I had to answer this for real.
**Ingress — more went in than you pasted.** You sent a stack trace; the harness opened the file, and the file opened the config beside it. You asked it to fix a query; it read the dump you had left in the working directory to reproduce the bug. The effective context is assembled by your tooling, not by your message, and almost nobody has looked at the actual request body their agent sends.
**Persistence — the copies outlive the session.** The provider's context is one destination, governed by whatever retention your tier and contract actually specify, which is a different question from training and worth separating carefully. Your own agent traces are a second, and they capture tool returns in full because body capture defaults to on and the default was chosen before your first sensitive call. The prompt cache is a third. Your CI logs are a fourth, and they are usually the least protected of the four.
**Egress — three ways it leaves, only one of which people watch.** Generated artifacts are the permanent one: the agent reproduces what it read into fixtures, docs, comments and commit messages, and once that is committed, deleting the file does not remove it from history. The second is injection: a dependency's README, an issue body, a scraped page or a tool result can carry instructions, and an agent holding your data plus any network-capable tool is a delivery mechanism. The third is simply the next session, and the next engineer.
Then the boundary. Everything below runs in our CI today:
- **Fixtures must declare themselves fake or they are refused at load time.** A test double that claims to be production-certified is rejected by the contract. Unmarked data does not get to be trusted by default.
- **Seed data is fake by construction**, not by convention: invalid check digits, reserved phone ranges, reserved email domains, all enforced by a checker that runs before commit and *undoes the seed* when violated. It is an allow rule, not a block list — blocking one real email domain just lets the next one through.
- **Sensitive content is never written, not even briefly.** A reset token is hashed, and the body carrying it in clear text is never inserted at all, because writing and then deleting leaves the value in the database between the two operations, and in the write-ahead log after that.
- **Output is scanned by value, against what the process actually decrypted** — not against a list of field names somebody remembered to maintain. A list of names protects the fields someone thought of.
- **One test patches the network stack** (`net`, `http`, `https`, `fetch`) so that any outbound call throws, proving a code path made no call at all rather than asserting it politely.
- **An import-graph scan enforces that nothing which talks to the model can reach a credential.** The list of files that talk to the model is *derived from the imports themselves*, so a file that starts calling the model tomorrow is covered without anyone registering it. It runs in both directions, strips comments before scanning so it doesn't fail on the comment explaining the rule, and carries a positive control proving it can still catch a real violation.
Then the counter-proof: put the leak back, and watch the scan go red.
And the limits, stated plainly. A marker's absence proves a property on the path you tested; it is not anonymization. A type contract is not authorization. Classifiers miss things, and a free-text field will carry whatever someone typed into it. None of this is a compliance claim.
The honest framing is not "stop pasting things." People will paste things, because the alternative is being slower than the person next to them. The framing that works is the one we already use for every other untrusted boundary: assume data will enter, decide per destination what may leave, and make the decision a test rather than a habit.
The AI must not invent the law: stopping fabricated facts in an AI-built legal SaaS
Everyone worries about hallucinations in chat. The quieter version lives in the code your agent writes: a plausible default, a field name copied from a test fixture, a status the source never sent. In most apps that is a bug. In a legal SaaS, it is a missed deadline or an invoice with the wrong tax.
PS JUS is a practice-management SaaS for Brazilian law firms, built entirely with Claude Code by a small studio. It reads court publications, tracks deadlines and issues service invoices in a country with 5,570 municipalities, each with its own tax rules. Here are five places where agent-written code invented a fact, and the rule that now makes it impossible:
1. **Problem:** every case found in the court gazette was saved as "active", and the source never said so. **Solution:** store only what the source said; an empty value with a recorded origin means "we asked, and the source doesn't say".
2. **Problem:** the code read the field name the test fixture used, not the one the court API sends. The incremental sync silently stopped, and the suite stayed green because the fixture agreed with the bug. **Solution:** one owner per source field, fixtures that carry both spellings and must declare themselves fake.
3. **Problem:** a verifier read a proxy's 403 as "the court API is reachable". **Solution:** a 4xx doesn't prove the source answered; the verdict stays PENDING until a real call lands.
4. **Problem:** tax rates and municipal rules written from memory look exactly like facts. **Solution:** no numeric tax rate anywhere in the code (a scan fails the build), a missing rate is empty and never zero, the municipality list starts nearly empty, and an official layout only counts with a government source, date and hash.
5. **Problem:** "connected successfully" from something that never called anyone. **Solution:** simulated never becomes certified, and a receipt protocol is not an issued invoice.
The same rule applies to the AI feature inside the product, and the record shows why. Generative models invent citations to back up what they were about to say: fake precedents, fake statutes, fake quotes. Courts have sanctioned lawyers for filing them, from New York (Mata v. Avianca, 2023) to Wyoming (eight non-existent cases from a law firm's in-house AI, 2025) to Brazil, where a state court fined a lawyer 10% of the case value for ChatGPT-invented precedents and a federal court fined another 20 minimum wages for a made-up "procedural law of time" (both 2025). One tracker counts roughly 1,490 such court decisions worldwide. So the assistant in PS JUS never searches, never cites precedent and never argues a thesis. It reads one court publication it is given, explains in plain language what it says and what it requires, quotes deadlines exactly as written without calculating them, and receives only that text, never the client's records. Its answer comes in a fixed format, is born labeled "AI-generated, review", and only counts after a lawyer approves it, with the model, who generated it and who approved it on record.
The takeaway is a pattern for any domain whose facts come from outside, like law, tax, health or finance: your code may say "I don't know". It may never guess.
One firm, one database: making tenant leaks impossible when an AI writes your SaaS
Coding agents made it possible for founders and small studios, many without a software career, to build and sell SaaS. I'm one of them: a mechanical engineer who co-founded a small software studio in Brazil. Our case study is PS JUS, a SaaS for law firms built entirely with Claude Code, where every record is privileged legal information and one firm must never see another's. The lessons apply to any multi-customer product: a CRM, a clinic system, an HR tool.
Why take the risk at all? Because automating repetitive work pays twice. For the company, tasks that used to depend on someone remembering, like checking the official court gazette three times a day or setting up a new customer, run on their own and leave an audit trail. For the people, lawyers and staff stop copying the same data into three places and stop fearing the deadline nobody saw. That only holds if the automation can be trusted with other people's data.
Coding agents reason about the file in front of them. Tenant isolation is an invariant that lives everywhere else. So instead of asking the agent to remember it, we tried to make breaking it structurally impossible, and then kept finding the places where it still leaked.
Four problems every AI-built SaaS runs into, and what we did about each:
1. **Problem:** in a shared database, isolation is a `WHERE tenant_id = ?` in every query, and one the agent forgets leaks a firm's cases while every test passes. **Solution:** we removed the bug class. Each firm runs as its own process, OS user, database file, directory, service and set of secrets. There is no tenant column in the legal tables to forget.
2. **Problem:** physical isolation still leaks through everything that is shared: code defaults, external IDs, caches, the admin panel, backups. We found another firm's name in browser tab titles and in the first-access email, and calendar IDs that are unique per account, not per firm. **Solution:** every external ID is bound to its connection, branding is resolved from the tenant, and the admin panel is a separate process whose database has no table or column for legal content, enforced by a test.
3. **Problem:** tests pass for the wrong reason. One tenant in the fixtures, auto-increment IDs that collide across firms, runners that count printed "OK" lines. **Solution:** an isolation suite that boots two fictitious firms side by side and judges leaks by content canaries, and a runner that must fail two negative controls before it trusts its own count.
4. **Problem:** self-serve sign-up, which we are building for November (today a human still approves each new firm), turns onboarding into code nobody watches, and sensitive data leaks into the agent's context while you build. **Solution:** one provisioning door with human approval, a rehearsal on the exact version and typed confirmation; nothing sensitive in the provisioning payload; fixtures that must declare themselves fake; secrets encrypted per tenant; and code scans that fail the build when a new file breaks a rule.
You don't need to be a programmer to build and sell SaaS with AI. You do need two habits: make the invariants the AI can't see impossible to break, and prove isolation with fictitious customers before a single real record goes in. Every leak in this talk happened in agent-written code, and every one was caught on fake firms.
Please note that Sessionize is not responsible for the accuracy or validity of the data provided by speakers. If you suspect this profile to be fake or spam, please let us know.
Jump to top