-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsyncabill.html
More file actions
284 lines (274 loc) · 13.5 KB
/
Copy pathsyncabill.html
File metadata and controls
284 lines (274 loc) · 13.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="How Daniel Gaskins built SyncABill, an AI invoice workflow with human review, accounting integrations, and deterministic financial controls."
/>
<meta name="theme-color" content="#0b0d0c" />
<meta property="og:title" content="SyncABill — Applied AI Case Study" />
<meta
property="og:description"
content="Gemini reads the invoice. Deterministic code controls what reaches QuickBooks or Xero."
/>
<meta property="og:type" content="article" />
<meta property="og:url" content="https://danielgaskins.com/syncabill.html" />
<meta property="og:site_name" content="Daniel Gaskins" />
<meta property="og:image" content="https://danielgaskins.com/assets/img/syncabill-product-demo-poster.jpg" />
<meta property="og:image:width" content="1920" />
<meta property="og:image:height" content="1080" />
<meta property="og:image:alt" content="SyncABill invoice review workflow product demonstration" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="SyncABill — Applied AI Invoice Workflow Case Study" />
<meta name="twitter:description" content="Gemini reads the invoice. Deterministic code controls what reaches QuickBooks or Xero." />
<meta name="twitter:image" content="https://danielgaskins.com/assets/img/syncabill-product-demo-poster.jpg" />
<meta name="twitter:image:alt" content="SyncABill invoice review workflow product demonstration" />
<link rel="canonical" href="https://danielgaskins.com/syncabill.html" />
<title>SyncABill — Applied AI — Daniel Gaskins</title>
<link rel="icon" href="./favicon.svg" type="image/svg+xml" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Manrope:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="./styles.css" />
<script src="./script.js" defer></script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"@id": "https://danielgaskins.com/syncabill.html#software",
"name": "SyncABill",
"description": "AI-assisted invoice intake, validation, human review, and accounting synchronization.",
"url": "https://syncabill.com/",
"applicationCategory": "BusinessApplication",
"operatingSystem": "Web",
"author": {"@id": "https://danielgaskins.com/#daniel-gaskins", "@type": "Person", "name": "Daniel Gaskins"}
}
</script>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header" data-header>
<a class="wordmark" href="./" aria-label="Daniel Gaskins, home">
<span>DG</span>
<span class="wordmark__name">Daniel Gaskins</span>
</a>
<button class="nav-toggle" type="button" aria-expanded="false" aria-controls="site-nav">
<span></span><span></span>
<span class="sr-only">Toggle navigation</span>
</button>
<nav id="site-nav" class="site-nav" aria-label="Primary navigation">
<a href="./#work">Work</a>
<a href="./#capabilities">How I work</a>
<a href="./blog.html">Blog</a>
<a href="./#about">About</a>
<a href="./resume.html">Résumé</a>
<a class="nav-cta" href="mailto:hello@danielgaskins.com">Talk with me</a>
</nav>
</header>
<main id="main" class="case-study">
<section class="case-hero section-shell">
<p class="eyebrow"><span class="status-dot"></span> Applied AI case study / 2025—present</p>
<h1>An invoice can be read correctly and still create the wrong bill.</h1>
<p class="case-hero__lede">
I built SyncABill to turn emailed and uploaded invoices into reviewable accounting
records. Gemini reads the document. Deterministic code controls what happens next.
</p>
<div class="case-hero__actions">
<a class="button button--primary" href="#demo">Watch the product demo</a>
<a class="button button--quiet" href="#workflow">See the architecture</a>
<a class="button button--quiet" href="https://syncabill.com" target="_blank" rel="noreferrer">Visit SyncABill</a>
</div>
</section>
<section id="demo" class="case-demo">
<div class="section-shell case-demo__inner">
<div class="case-demo__intro">
<p class="section-index">PRODUCT TOUR / 71 SECONDS</p>
<h2>From one invoice to a bill ready for review.</h2>
<p>
The demo follows an invoice through upload, extraction, arithmetic checks,
source review, correction, and approval. It uses a fictional company and
sample document, so no customer data appears in the recording.
</p>
</div>
<div class="case-demo__frame">
<video
controls
playsinline
preload="metadata"
poster="./assets/img/syncabill-product-demo-poster.jpg"
aria-label="SyncABill product demonstration"
>
<source src="./assets/video/syncabill-product-demo.mp4" type="video/mp4" />
Your browser does not support embedded video.
<a href="./assets/video/syncabill-product-demo.mp4">Download the demonstration</a>.
</video>
</div>
</div>
</section>
<section class="case-signal" aria-label="SyncABill scope">
<div class="section-shell case-signal__grid">
<div><strong>04</strong><span>invoice intake paths</span></div>
<div><strong>02</strong><span>accounting integrations</span></div>
<div><strong>01</strong><span>controller-owned review policy</span></div>
<div><strong>00</strong><span>model-authorized financial writes</span></div>
</div>
</section>
<section id="workflow" class="case-section section-shell">
<div class="case-section__label">
<p class="section-index">01 / THE WORKFLOW</p>
</div>
<div class="case-section__body">
<h2>The model reads. The application decides.</h2>
<p class="case-section__lead">
Invoices arrive by upload, forwarding, Gmail, or Microsoft 365. Before Gemini runs,
SyncABill checks the file, rejects exact duplicates, reserves plan usage, and keeps
the original document for review.
</p>
<p>
The product uses a React/Vite frontend and TypeScript and Node.js services on Firebase
Cloud Functions. Firestore carries tenant, invoice, job, lock, and audit state. Cloud
Storage holds source documents, while Firebase Auth, App Check, and Secret Manager
protect client calls and provider credentials.
</p>
<div class="case-flow" aria-label="SyncABill invoice lifecycle">
<div><span>01</span><strong>Receive</strong><small>email, inbox, or upload</small></div>
<i>→</i>
<div><span>02</span><strong>Extract</strong><small>Gemini returns structured fields</small></div>
<i>→</i>
<div><span>03</span><strong>Check</strong><small>rules, arithmetic, and accounts</small></div>
<i>→</i>
<div><span>04</span><strong>Sync</strong><small>approved bill reaches the ledger</small></div>
</div>
<p>
The model proposes vendor names, dates, totals, line items, and expense accounts.
Application code checks the response, resolves the account against the real ledger,
and applies the controller’s review rules before QuickBooks Online or Xero receives it.
</p>
</div>
</section>
<section class="case-section case-section--dark">
<div class="section-shell case-section__inner">
<div class="case-section__label">
<p class="section-index">02 / WHY THE SHELL MATTERS</p>
</div>
<div class="case-section__body">
<h2>A fluent answer is not permission to move money.</h2>
<div class="case-task-list">
<article>
<span>ACCESS</span>
<h3>Who may act?</h3>
<p>Firebase identity, workspace membership, and roles decide who can review, approve, or sync a bill.</p>
</article>
<article>
<span>ACCURACY</span>
<h3>Does the bill add up?</h3>
<p>Ordinary code checks totals and confirms that suggested accounts exist in the connected ledger.</p>
</article>
<article>
<span>REVIEW</span>
<h3>Should a person see it?</h3>
<p>The account controller sets the review policy. The model does not choose its own level of oversight.</p>
</article>
<article>
<span>RETRIES</span>
<h3>Will a retry create two bills?</h3>
<p>Content hashes, operation locks, duplicate checks, and provider idempotency protect the manual sync path.</p>
</article>
</div>
</div>
</div>
</section>
<section class="case-section section-shell">
<div class="case-section__label">
<p class="section-index">03 / SECURITY</p>
</div>
<div class="case-section__body">
<h2>Financial documents make security part of the product.</h2>
<p class="case-section__lead">
I completed Google’s CASA Tier 2 security assessment and brought SyncABill to SOC 2
readiness. The product uses least-privilege OAuth, encrypted provider credentials,
signed uploads, role checks, audit events, and bounded retries.
</p>
<div class="case-comparison">
<div>
<span>MODEL OUTPUT</span>
<p>A candidate set of facts parsed from an untrusted document.</p>
</div>
<div>
<span>APPLICATION DECISION</span>
<p>A checked, authorized, recorded action with a visible failure state.</p>
</div>
</div>
<p>
CASA Tier 2 is a completed security assessment. SOC 2 readiness means the controls
were prepared for an audit. It is not a claim that SyncABill completed SOC 2 certification.
</p>
</div>
</section>
<section class="case-section case-section--paper-dark">
<div class="section-shell case-section__inner">
<div class="case-section__label">
<p class="section-index">04 / THE AUDIT</p>
</div>
<div class="case-section__body">
<h2>The architecture review found work worth doing.</h2>
<div class="case-columns">
<div>
<h3>What is working</h3>
<ul>
<li>File checks and deduplication before model spend</li>
<li>Structured extraction followed by deterministic validation</li>
<li>Controller-owned review rules</li>
<li>Manual ledger locks and provider idempotency</li>
<li>Persistent status and audit history</li>
</ul>
</div>
<div>
<h3>What comes next</h3>
<ul>
<li>Move integration secrets behind a backend-only boundary</li>
<li>Give automatic sync the manual path’s safety controls</li>
<li>Add a labeled invoice evaluation set</li>
<li>Record model, prompt, cost, and correction data</li>
<li>Move long-running work to a durable queue</li>
</ul>
</div>
</div>
<div class="case-note">
<span>CURRENT STATE</span>
<p>
SyncABill is an early production product. Accounting auto-sync is disabled.
The current production model is Gemini 3.5 Flash-Lite. A versioned invoice test
set remains planned work for measuring model changes and catching regressions.
</p>
</div>
</div>
</div>
</section>
<section class="case-next section-shell">
<p class="section-index">05 / WHAT I OWNED</p>
<h2>From the first workflow to the security review.</h2>
<p>
I founded the product and own its requirements, architecture, testing, review,
failure handling, integrations, and operation. I use coding agents to implement
software, then inspect and test what they produce. The product decisions and accepted
results remain my responsibility.
</p>
<div class="case-next__actions">
<a class="button button--primary" href="mailto:hello@danielgaskins.com">Ask me about the system</a>
<a class="button button--quiet" href="./#work">Back to selected work</a>
</div>
</section>
</main>
<footer class="site-footer section-shell">
<p>© <span data-year></span> Daniel Gaskins</p>
<p>Physics · Models · Products</p>
<a href="#main">Back to top ↑</a>
</footer>
</body>
</html>