AutoFill Portal is a Chrome browser extension that helps licensed contractors fill out government permit application forms automatically using data from a spreadsheet (CSV or Excel file). The extension communicates with a hosted backend server (Railway) to perform intelligent field matching, learn from corrections, and optionally generate AI suggestions.
The extension includes an optional contractor profile where you can enter your name or
company name, contractor license number, insurance policy number, phone number, email address,
and business address. This data is stored exclusively in your browser using
chrome.storage.local. It is sent to your backend server only when you trigger a
form-fill action, solely to pre-fill contractor-identity fields on the current form. The server
does not log or retain these values.
When you upload a CSV or Excel file, the file is sent to and stored on your hosted backend
server as uploads/active.csv. This file typically contains project addresses,
permit details, and owner contact information. It remains on the server until you upload a
replacement. We do not share, sell, or analyze this file for any purpose other than
powering the field-matching feature.
Each time you click “Apply All” or “Apply Selected,” the extension
sends a summary record to the server. This record is stored in the fill_sessions
database table and contains:
chrome.storage.local. It contains no
personal information and cannot be used to identify you.permits.city.gov)No form values, project addresses, names, or personally identifying information are included. Records older than 90 days are deleted automatically.
When you manually swap a field’s assigned column in the review view or the on-page
alt panel, a correction record is stored in the corrections table containing:
These records are used to improve future auto-fill results on the same portal domain and are not user-keyed. No form values or personal information are included.
Additionally, when you pick an alternative column in the alt panel, the extension extracts
a structural pattern from your correction and stores it in the learned_rules
table. This record contains only normalized field-name tokens, label tokens, and the target
column name — no user values, addresses, names, or any personally identifying
information are ever stored in learned rules. These structural patterns are used to
improve matching on other portals and for other users of the same deployment.
When you fill forms, a statistical fingerprint of the field-to-column mapping is recorded
in the portal_mappings table. Each record contains:
These records improve matching for all users on the same portal domain. They contain no personally identifying information. Records not updated for 180 days are deleted automatically.
If the extension detects that a form submission was rejected (e.g., a validation error page
is shown), it may record a rejection event in the rejection_events table containing:
Rejection events are used to identify portals that need improved matching. No form values, no contractor profile data, and no personally identifying information are recorded.
If you voluntarily submit feedback using the “Feedback” button in the extension
popup, the following information is stored in the feedback table:
Feedback is used to improve matching quality and identify bugs. It is never shared with third parties and is visible only to the developer in the admin dashboard. Submitting feedback is always optional.
When you fill a form, a snapshot of the fill outcome is stored in the
submission_history table keyed by an anonymous fingerprint of your CSV row
(not your identity). This record contains:
This is used to detect when you revisit a portal to resubmit, pre-populate fields that were accepted previously, and detect changed fields. No contractor profile data is stored in submission snapshots.
When you complete onboarding steps (e.g., first CSV upload, first fill), a record is stored
in the onboarding_events table containing your anonymous user ID and the step name.
This is used to measure product adoption and is never linked to your identity.
When you use the PDF Filler feature at /pdf-fill, your PDF document is
processed entirely within your browser using JavaScript.
No PDF content, PDF bytes, or document text is ever transmitted to our servers.
We receive only the AcroForm field names extracted from your PDF — not their values,
not the document content — for the purpose of matching them to your project data using the
standard /api/match-fields endpoint (same as HTML form fills). After you save a
filled PDF, a fill-success signal is sent containing field names and matched CSV column names
only (see §2c for signal contents). This privacy guarantee is architectural: the Railway backend
has no endpoint that accepts PDF bytes and no code path that processes them.
When loading a PDF from a URL (e.g., a link detected by the extension on a government permit
portal), the document is fetched through our servers via the /api/pdf-proxy
endpoint solely to bypass browser security restrictions that prevent direct cross-origin
downloads. The PDF bytes are immediately streamed to your browser and are never stored, logged,
or retained in any form on the server.
When you use the PDF Filler feature, each page of your PDF is rendered as an image in your browser and sent to Anthropic’s Claude AI API solely to identify the form fields and their labels. These images contain only the blank form layout — not your personal data or filled values. Anthropic does not store these images beyond the duration of the API call. Analysis results are cached on our servers by form fingerprint so the same form is never analyzed twice. We never send filled PDF content or personal information to Anthropic.
When you create an account at autofillportal.com/signup, we collect and store
your email address, a bcrypt-hashed password (we never store your plain-text
password), and a randomly generated API key used to authenticate the extension. We also record
the account creation timestamp, your last login timestamp, and your subscription plan. Stripe
customer and subscription IDs are stored when you subscribe to a paid plan; Stripe processes
payment data and we never store full card numbers. Your API key can be rotated at any time from
the account page, which immediately invalidates the previous key.
Contractor profile, preferences, form type profiles, session context, edit history,
self-learning signals, and your anonymous user ID are stored in
chrome.storage.local and chrome.storage.session.
This data remains on your device and is controlled entirely by Chrome.
The production server uses a PostgreSQL database hosted on Railway. The following tables are used:
| Table | Contents | Retention |
|---|---|---|
fill_sessions |
Anonymous telemetry: domain, form type, field counts, fill method breakdown, average confidence (see §2c) | 90 days |
corrections |
Domain + HTML field name → CSV column name (see §2d) | Indefinite |
portal_mappings |
Field fingerprint → column name + confidence — no values stored (see §2e) | 180 days since last use |
rejection_events |
Rejection signals + flagged field names (see §2f) | Indefinite |
feedback |
Voluntary user feedback messages (see §2g) | Indefinite |
submission_history |
Per-project fill snapshots keyed by anonymous row fingerprint (see §2h) | Indefinite |
portal_form_versions |
Portal form structure hashes for change detection — no values stored | Indefinite |
field_concepts |
Cross-portal field name → canonical column mappings — no values stored | Indefinite |
field_gap_log |
Per-field fill/gap counters per portal domain — no values stored | Indefinite |
jurisdiction_rules |
Jurisdiction-level shared field patterns derived from portal_mappings — no values stored | Indefinite |
portal_section_types |
Section classification votes per portal domain (contractor / project / owner / neutral) — no form content stored | Indefinite |
portal_mapping_conflicts |
Log of mapping conflicts where a new correction disagreed with a high-confidence existing mapping — field fingerprints and column names only | Indefinite |
onboarding_events |
Anonymous user ID + onboarding step name (see §2i) | Indefinite |
error_events |
Server-side error type and endpoint for error-rate alerting — no user data | Indefinite |
fill_sessions_v2 |
Extended session telemetry including per-section confidence scores — same data as fill_sessions, no additional personal information | 90 days |
portal_detection_stats |
Per-domain average field detection latency (milliseconds) — no user data | Indefinite |
learned_rules |
Structural field-name/label patterns extracted from corrections — zero user data: only normalized tokens and column names (see §2d) | Indefinite |
rule_signals |
Per-domain positive/negative signals for each learned rule — domain name and signal type only, no user data | Indefinite |
learned_meta_rules |
Clustered rule groups aggregated from learned_rules — structural patterns only, no user data | Indefinite |
users |
Account email, bcrypt password hash, API key, subscription plan, last login timestamp, Stripe customer/subscription IDs (see §2l) — only for registered users | Until account deletion request |
In local development mode (no DATABASE_URL), the same data is stored in JSON
files in the uploads/ directory. Fill logs are capped at 10,000 entries.
AutoFill Portal uses the following third-party services:
ANTHROPIC_API_KEY environment variable is configured on your server:
No personally identifying information (names, addresses, license numbers, contact details) is sent to Anthropic. These values come from your “My Info” profile and remain in your browser. Anthropic’s privacy policy applies: anthropic.com/privacy.
The AI feature requires an ANTHROPIC_API_KEY configured on your server.
It is disabled by default if no key is present.
fill_sessions, fill_sessions_v2) is
deleted automatically after 90 days. Cleanup runs on server startup
and every 24 hours.POST /api/user/delete request with your anonymous user ID
(found in chrome.storage.local under the key userId).
This removes all fill_sessions rows tied to that ID. Corrections,
portal mappings, and learned rules are not user-keyed and cannot be individually deleted
via this endpoint./account. To
permanently delete your account record (email, password hash, API key), email
support@autofillportal.com
from the address associated with your account. We will delete your user record within
30 days. Deletion is irreversible and you will lose access to the service immediately.All communication between the extension and the backend server uses HTTPS. The backend
API is authenticated with an API key configured in your deployment. You should configure the
extension only to communicate with servers you control. Rate limiting (60 requests per minute
globally, 10 requests per minute for AI endpoints) is enforced on the server to protect
service availability. The extension declares the scripting permission, which is used
exclusively to synchronize third-party rich-text editors (TinyMCE, CKEditor) with filled
values when those editors are embedded in permit portal pages. The background service worker
calls chrome.scripting.executeScript with world: 'MAIN' to invoke
the editor’s native API. This permission is never used to inject arbitrary code or
monitor page content.
AutoFill Portal is designed for use by licensed contractors and business professionals. It is not intended for use by persons under 18 years of age, and we do not knowingly collect information from minors.
We may update this Privacy Policy from time to time. The “Last updated” date at the top of this page reflects the most recent revision. Continued use of the extension after a policy update constitutes acceptance of the revised terms.
If you have questions about this Privacy Policy or wish to request deletion of your server-side data, please contact us at support@autofillportal.com.