DeliverVault
Inspiration
It started with a real argument.
A freelancer friend spent six weeks building a web app for a client. When it was time to invoice, the client disputed three deliverables — claimed they hadn't approved them, that the scope had changed, that the emails "didn't count" as formal sign-off. My friend had nothing. A WhatsApp thread, a few email replies, and a gut feeling that he'd done everything right.
He lost the dispute. Not because he was wrong — but because he couldn't prove it.
That conversation stuck. Every freelancer we talked to had a version of that story. The tools exist — Gmail, Slack, GitHub, Notion — but they're completely disconnected. There's no consent chain. No audit trail. No way to show a client "here is exactly what happened, who authorized it, and when."
Trust between freelancers and clients is broken by default, and nobody was building the infrastructure to fix it.
We wanted to build something that changed the relationship. Not just a better proposal tool — a system where every action is authorized, auditable, and provable.
What it does
DeliverVault turns a raw proposal or client brief into a visual, step-by-step approval workflow — and then actually executes it.
You paste your proposal text. That's the entire input. Our AI reads it and extracts a structured workflow: the project title, client name, contract value, and 3–7 concrete steps with realistic timelines. Each step gets automatically connected to the service action it represents — sending a contract draft via Gmail, posting a milestone update to Slack, creating a GitHub issue for code delivery, logging a spec in Notion.
Then the interesting part starts.
Every service action runs through Auth0 Token Vault. When a user connects their Gmail once, Auth0 intercepts the OAuth callback and stores that token encrypted — DeliverVault never sees it, never writes it to a database. When a step is approved and the Gmail action fires, the backend requests a short-lived token via RFC 8693 token exchange, uses it for exactly one email send, and it expires. The user can revoke that connection at any moment. The audit log records everything.
For steps that need human sign-off, we built two paths. The clean one uses Auth0 CIBA — a push notification goes to the reviewer's phone via Auth0 Guardian. They tap approve on their lock screen. The workflow canvas updates in real time. The other path sends a single-use email link that expires in 48 hours — for mentors or clients who don't have Auth0.
Beyond that: an AI co-pilot that rewrites proposal copy and flags risky contract clauses, real-time step updates via Socket.io, a full paginated audit trail, and optional Stripe payment link generation when the final step is approved.
How we built it
The frontend is React with TypeScript, built in Lovable. The workflow canvas uses React Flow. Animations are Framer Motion and GSAP. The whole app runs in demo mode with no backend — judges can explore the full UI without any setup.
The backend is Express on Render's free tier. Auth0 handles JWT validation, Token Vault credential management via the Management API, and CIBA backchannel authentication. MongoDB Atlas M0 stores proposals, audit logs, CIBA requests, and mentor tokens — all with TTL indexes for automatic cleanup.
The AI runs across a 5-provider waterfall: Groq, Cerebras, SambaNova, Google Gemini, and OpenRouter. Every provider is free tier. If Groq hits its daily limit, Cerebras picks up in milliseconds. Combined daily capacity is over 18,000 requests. Response caching means identical rewrites return in under 1ms.
We added a stale-while-revalidate in-process cache to make the free Render tier feel fast — proposal lists return in under 5ms after the first load. Audit log writes are fire-and-forget via setImmediate so they never block a response. A self-ping every 14 minutes prevents Render's cold-start sleep.
Real-time updates use Socket.io with JWT-authenticated connections. When a mentor approves a step via CIBA — their phone, our backend, Auth0, back to the canvas — the node turns green and confetti fires within two seconds of the tap.
Challenges we ran into
Auth0 Token Vault is not well-documented for this exact use case. The docs explain what it does clearly, but finding a practical Node.js example of "request a short-lived Gmail token for an authenticated user via credential ID exchange" required reading multiple RFCs, digging through the Management API reference, and a lot of trial and error. The RFC 8693 flow is elegant once it clicks — but nothing in the docs draws a straight line from "user connected Gmail" to "backend makes a Gmail API call."
CIBA polling and the free tier don't love each other. Auth0's CIBA requires polling /oauth/token every few seconds. On Render's free tier, a cold server takes 30 seconds to wake — which completely breaks the real-time experience. The keep-alive ping solved it, but it required understanding exactly how Render's sleep timer works and cutting it close enough to actually matter.
Port confusion burned hours. Frontend on 5000, backend on 3001, Vite proxy bridging them — but Auth0 callback URLs, the CORS config, and the API base URL all had to agree on this. We had three different places with the wrong port hardcoded, and the error messages for each failure pointed to completely unrelated causes.
Making AI responses feel human. When you ask the co-pilot to "add a pricing table," it occasionally returns JSON. When you ask it to rewrite something, it returns prose. We needed a message renderer that detects JSON and formats it as a proper table or risk card, while falling back to plain text for conversational replies. That component went through four full rewrites.
Accomplishments that we're proud of
The consent chain works end-to-end. Not mocked, not simulated. Connect your Gmail, approve a step — an email goes out from your real account. Connect GitHub — an issue gets created in your real repo. The Token Vault integration means every action is traceable: the credential ID that was exchanged, the timestamp, the outcome, all in the audit log.
We're proud of the 5-provider AI waterfall. It was straightforward to build and it completely eliminates the "AI is down" failure mode. In three days of testing, all five providers were never simultaneously unavailable. The combined free tier is genuinely sufficient for a production app at reasonable scale.
The CIBA mentor approval flow working in real time is the demo moment that lands hardest. Freelancer hits a button, mentor's phone buzzes 3 seconds later, mentor taps approve, the canvas updates. It's the kind of thing that reads better as a demo than as a feature description.
Demo mode might be our most underrated decision. The entire application runs without a backend, database, or Auth0 credentials. For a hackathon where judges have five minutes — that matters more than almost anything else.
What we learned
Token Vault changes the trust model, not just the security posture. We kept saying DeliverVault was "more secure" because credentials aren't in our database. That's true but it's not the interesting part. The interesting part is visibility — users can see which connections are active, what each one authorizes, and revoke any of them instantly. That transparency is what actually makes clients comfortable with automation touching their project communication. The security improvement is a consequence of the transparency improvement.
CIBA is underused because nobody shows a natural use case for it. Every example we read described the same abstract banking scenario. Once we had the mentor approval flow working, it was immediately obvious why you'd want this pattern — and how it applies to any AI agent that needs human checkpoints before taking high-stakes actions. The use case was the explanation.
Free tier is a real engineering constraint, not just a cost consideration. Cold starts, rate limits, connection limits, storage caps — every architectural decision had a free tier implication. It made us better at prioritizing what had to be fast (proposal loads, step approvals) versus what could be slightly slower (audit log pagination, connection testing). The cache layer and the keep-alive aren't workarounds — they're the right choices for any latency-sensitive app on shared infrastructure.
What's next for DeliverVault
The revocation flow deserves much more surface area. Right now it's one button on the Connections page. It should be visible on every step that used a token — showing exactly which credential was exchanged, with inline revocation. Auth0 gives us all the data to build that. We ran out of time.
A client-facing portal — a read-only live view of the proposal workflow, like a FedEx tracking page for a project. Clients shouldn't need to email "where are we on this?" They should have a URL they can bookmark.
Multi-freelancer agency mode. Right now proposals belong to one user. A team workspace where proposals can be assigned to different freelancers — each authenticated separately, each with their own Token Vault credentials — would make DeliverVault useful for small agencies, not just solo operators.
And the AI needs to grow into an actual agent. The current co-pilot is a chat interface. What it should be is something that proactively analyzes proposals for scope creep risk, flags payment terms that typically lead to disputes, and suggests protective contract language before you even ask. The infrastructure is already there. The intelligence needs to catch up.
📝 Bonus Blog Post: What We Actually Learned Building with Auth0 Token Vault
This section is submitted for the Bonus Blog Post Prize. It covers our Token Vault implementation experience in depth and is written as developer reflection — materially different from the project description above.
When we started DeliverVault, Token Vault was an item on a requirements checklist. By the time we finished, it had reshaped how we think about authorization entirely.
Most OAuth implementations are quietly terrifying
The standard pattern for storing third-party credentials: complete the OAuth flow, get an access token and refresh token, encrypt them, write them to your database. Done.
That means your MongoDB is holding the keys to every user's Gmail account. Every GitHub repo. Every Slack workspace. If your database has a misconfiguration, a leaked backup, or an injection vulnerability — your users' external services are exposed. Not just their account with you. Everything they connected.
This is such a normalized pattern that most developers don't stop to think about it. We certainly didn't until we started reading the Token Vault documentation and realized Auth0 was offering to remove these tokens from our infrastructure entirely — not store them more securely, but eliminate them from our attack surface completely.
The RFC 8693 token exchange took a few readings to click
The flow that makes Token Vault work in practice is RFC 8693 — the OAuth 2.0 Token Exchange spec. It's not complicated once you understand it, but it's not explained well anywhere practical.
Here's the actual flow: instead of storing a Gmail access token, you store nothing. Auth0 stores it. You get back a credential_id — an opaque identifier. When you need to call Gmail, you send that credential_id to Auth0's token endpoint with grant_type: urn:ietf:params:oauth:grant-type:token-exchange, and Auth0 responds with a short-lived access token.
Short-lived is the key. This token expires in minutes. Your backend cannot persist it in any meaningful way. You use it, it's gone.
The first time our full flow worked — user connects Gmail, Token Vault stores it, step approved, backend exchanges credential ID for access token, Gmail send succeeds, token expires, audit log records everything — we just sat with it for a moment. That's what authorization is supposed to feel like.
CIBA is the right answer to a problem nobody explains well
Every CIBA documentation example describes the same scenario: a user initiates a bank transfer, a back-office system needs to approve it. Technically accurate, completely abstract. We read those docs three times and still weren't sure what we were building toward.
The scenario that made it click was our mentor approval flow. A freelancer shouldn't be the only person who can approve a final payment step. They need someone to sign off — a senior partner, a mentor, a client. That person might not have an account on DeliverVault. The approval needs to happen asynchronously, on their phone.
That's exactly what CIBA does. Freelancer hits a button → backend calls /bc-authorize → Auth0 Guardian sends a push to the mentor's device → backend polls every five seconds → mentor taps approve → step completes → canvas updates via Socket.io. Eight seconds, end to end. The mentor never touches our app.
The pattern generalizes to any human-in-the-loop scenario: AI agents requesting permission before high-stakes actions, financial approvals above a threshold, any situation where automation needs a human checkpoint. We built it for freelancer workflows. It works for any consent-requiring action in an AI agent pipeline.
Three things we wish we'd known on day one
The M2M app and the SPA app are completely separate. Your backend needs a Machine-to-Machine application with Management API scopes (read:user_credentials, delete:user_credentials) to interact with Token Vault. Your frontend needs a Single Page Application for user auth. Different client IDs, different capabilities, different places in the dashboard. Confusing them produces errors that have nothing to do with the actual problem.
Token Vault requires explicit opt-in per social connection. It's not automatic. For each connection (Google, GitHub, Slack), go to Authentication → Social → that connection → Settings → Token Storage → set to "Auth0 Token Vault." Skip this and the OAuth flow completes, but the token goes to default storage. The Management API credential endpoints return empty results with no error message telling you why.
Test the token exchange in isolation first. Write a fifteen-line script that gets a credential ID from the Management API and exchanges it for an access token. Verify it works before wiring it into application logic. We built the whole service action flow first and spent two hours debugging Gmail failures before discovering the exchange was returning 401 because our M2M app was missing the right Management API scopes.
What Token Vault actually unlocks
We kept describing DeliverVault as "more secure" because credentials aren't in our database. Accurate, but it misses the point.
The more interesting thing is what Token Vault makes visible. When a user can see their active connections — Gmail authorized, GitHub authorized, Slack not connected — and can revoke any of them in under a second, the relationship between user and application changes. It's not a black box anymore. They know what it has access to. They know they can take it back.
That visibility is what makes clients comfortable with an automated workflow touching their project communication. The email that went to their inbox wasn't sent by some vague system with unclear access to someone's Gmail. It was sent with a token that was explicitly authorized, used once, and expired. The audit log proves it.
Auth0 Token Vault doesn't just improve security. It makes consent explicit, reversible, and observable. Those are the properties that trust is actually built from. That's what we're taking forward from this.
Log in or sign up for Devpost to join the conversation.