← Forge Athletic Systems

Forge Athletic Systems: security and data handling overview

Prepared for institutional IT and compliance review.
Last verified against the production codebase on 2026-10-07.
Contact: aaron@forgeathleticsystems.com

What Forge is

A coaching platform for wrestling programs. Coaches plan practices, manage a roster, track weigh-ins and results, and review match film. Athletes get a separate mobile app where they see their own schedule, their coach's feedback, and log their own weight.

Architecture

Static pages and serverless functions on Netlify. Data, authentication and file storage on Supabase, which is managed PostgreSQL. There is no self-managed server.

Backups, stated precisely. Supabase takes managed backups of the database. Separately, a nightly job writes a per-program JSON snapshot to the owner's workstation, which is a full-disk-encrypted Mac (FileVault) in the owner's home, and keeps the last 28 days. Those snapshots contain roster rows, so they contain athlete names. They exist so a bad write can be undone within minutes rather than waiting on a support ticket, and one was used for exactly that on 2026-10-06. If your agreement requires that no copy of institutional data leave managed infrastructure, we will exclude your program from that job or move it to encrypted object storage; say which and it is a configuration change, not a rewrite.

Subprocessors

ServicePurposeReceives
NetlifyHosting, serverless functionsRequest traffic
SupabaseDatabase, authentication, file storageAll application data
StripePaymentsBilling contact and payment details
ResendTransactional emailRecipient email address, message body
AnthropicAI practice and season generation, scouting text parsingSee "What reaches an AI model" below
Google Analytics 4Aggregate traffic on the PUBLIC MARKETING SITE ONLYAnonymous page view data. It does not run on any signed-in page: not the coach application, not the athlete application. Removed from eleven application pages on 2026-10-07 so that the code matches this statement. In-product usage is measured from our own database rows instead, never by a third party.

No card data touches Forge servers. Stripe collects and holds it directly.

Athlete data we hold

First name, last name, email, phone, birth date, graduation year, gender, status, plus the wrestling facts a coach keeps: weight class, certified minimum weight, match results, attendance, and eligibility dates.

We do not hold, and the application has no field for: home address, Social Security number, transcripts, grades, medical history, insurance details, or any photo identification. Athletes cannot upload an image anywhere in the application.

The athlete profile page states this to athletes directly, so that a phishing attempt asking for those documents is recognizable as not coming from us.

Minors

An athlete record is created with the status pending_consent. In that state the record is invisible to every coach, including the coach who created it. It becomes visible only after a guardian opens a one-time tokenized link and gives consent. The consent timestamp and the originating IP are recorded.

Guardians do not need an account. There is no parent login to provision, deprovision or audit.

Under-18 athletes who join a team with a join code are routed through the same guardian consent step before activation. Recruiting visibility for a minor requires a separate, explicit guardian consent.

Access control

Authentication is Supabase Auth, and it is passwordless. A user enters an email address and receives a one-time code; Forge stores no passwords. Coaches and athletes use the same authentication system and separate application surfaces. The trade-off is stated under "What we do not have": there is no password to phish or reuse, and equally no second factor beyond possession of the mailbox.

Authorization is PostgreSQL row-level security, enforced in the database rather than in application code, on every table. A coach reaches only his own team's rows. An athlete reaches only his own.

Two properties of this design are worth stating plainly:

  1. Row-level security is row-level, not column-level. Coaches and athletes are both the same database role, so a coach can read every column on an athlete who belongs to his team, including birth date. This is intended. A coach knowing his wrestler's birthday and weight class is the normal operation of the product.
  2. Column-scoped writes, where a coach may correct a wrestling fact but not overwrite an athlete's own entries, are implemented as security definer database functions with a pinned search_path, not as policies, because a policy cannot make that distinction.

File storage

Two buckets.

match-video is private. Access policies key on the team identifier as the first path segment, so a coach reads, uploads and deletes only under his own team's prefix. Maximum 2 GB, video MIME types only.

program-photos is public. It holds one branding image per program, uploaded by the coach. Maximum 8 MB, image MIME types only. No athlete data is stored in it.

What reaches an AI model

Two features call Anthropic's API.

Season and practice generation sends only the coach's intake: sport, level, division, season dates, goals, team name, conditioning preference and tier. No roster, no athlete record and no athlete identifier is read from the database or included. This was verified field by field on 2026-10-05.

Scouting text parsing sends text that the coach pastes in himself, capped at 24,000 characters. That text may contain opponent names, because that is what a coach is pasting. Nothing is read from our database and sent.

Training. Anthropic's commercial terms state that Anthropic may not train models on customer content, inputs or outputs. Forge is a paid API customer and is on those terms. No athlete record is ever used to train a model, by us or by Anthropic.

Retention at Anthropic. Not training is a separate question from not retaining, and reviewers ask it next, so here is the honest answer. Anthropic holds API request and response data for a limited period for abuse monitoring under its standard commercial terms. Forge has not arranged zero-retention processing. We judge the exposure low because of the paragraphs above: the season call carries no athlete data at all, and the scouting call carries only text the coach chose to paste. If your institution requires zero retention for any third-party AI processing, tell us and we will take it up with Anthropic before you sign.

Turning it off. Both features are optional. A program that does not use the season builder or the scouting paste has no data leaving Forge for an AI model.

Browser and transport controls

ControlSetting
TLSEnforced. Plain HTTP 301s to HTTPS.
HSTSmax-age=31536000; includeSubDomains
FramingX-Frame-Options: SAMEORIGIN, and DENY on the athlete app, which holds minors' data
MIME sniffingX-Content-Type-Options: nosniff
Referrerstrict-origin-when-cross-origin, so a path containing a team id never reaches a third party
PermissionsCamera, microphone, geolocation, payment, USB and motion sensors all denied. Forge asks for none of them.

Third-party JavaScript. The application loads one third-party library at runtime, the Supabase client. It is pinned to an exact version and carries a SHA-384 Subresource Integrity hash, so a browser refuses to execute it if the CDN ever serves different bytes. Added 2026-10-07; before that it tracked the latest 2.x release, which is a supply chain exposure on pages that handle student data. No analytics or advertising script runs on any signed-in page.

Content-Security-Policy is not yet set. It is the one control on this list we have not shipped. The application embeds YouTube for film and the marketing site links to a dozen outside wrestling vendors, so a policy written without testing would break film playback for a paying coach. We would rather tell you it is missing than ship one that silently fails open.

Public links. Three pages are reachable without a login: a team's schedule and record for families, a single match video opened from a link a coach sends, and the unsubscribe page. They are capability URLs, meaning possession of the link is the authorisation. Two things bound that risk: the payload is deliberately team-level only, with no athlete names, weights or per-wrestler records, and that exclusion is enforced in the serverless function rather than in the page, so the data never reaches the browser. The honest limitation is that the identifier is the team's primary key, so the link cannot be rotated to revoke it. If you need a revocable link we will issue one; it is a schema change, not a redesign.

Rate limiting. Authentication throttling is Supabase's. Forge's own functions do not implement per-caller rate limits beyond the free build quotas on the season generator. Stated plainly because it is a fair question.

Testing and release controls

Every deploy runs an automated gate before anything reaches hosting. There is no override flag.

One check in that gate, qa/rls_qa.mjs, connects as an unauthenticated user and attempts to read every table and view in the database. Any returned row fails the deploy. This exists because of a real finding, below.

Database changes are additive only. Application code is written to work against both the previous and the new schema, so a partially applied change cannot lock a user out.

Independent review

A third-party security review on 2026-09-12 found that plain database views bypassed row-level security, and that Supabase grants read access on new public objects by default. The reviewer retrieved billing and usage rows using the public API key.

Remediated the same day: views revoked from anonymous and authenticated roles and switched to security_invoker, default privileges revoked in the public schema, and schema files removed from the web root. The automated gate described above was added so that this class of defect cannot return silently. All findings from that review are closed.

Production has since been migrated entirely to Supabase's current key format. Legacy JWT-based API keys are disabled on the production project.

Availability

Automated checks run every 15 minutes against the public site, the application shell, a serverless function, the authentication endpoint and a live database read, with alerting on state change.

Incident response

A single named owner, reachable at aaron@forgeathleticsystems.com. Forge is a small company and does not maintain a 24-hour on-call rotation. We will commit to a notification window in writing as part of any agreement.

Data export and deletion

On request we export a program's full data set and delete it, including stored video. Deleting an athlete's authentication account leaves the athlete record with a null user reference rather than orphaning related rows.

Encryption at rest

Database, file storage and backups sit in Supabase, which encrypts data at rest with AES-256 on AWS-managed volumes. Forge operates no storage of its own, so there is no second place to ask about, with the one exception named under Architecture: the nightly JSON snapshot on the owner's workstation, which rests on a FileVault-encrypted disk.

Audit logging

EventWhere it is recordedKept
Sign-in, sign-out, one-time code issued and usedSupabase Auth logsPer Supabase plan retention
Every serverless function invocation, with statusNetlify function logsPer Netlify plan retention
Guardian consent for a minorIn the database, with timestamp and originating IPFor the life of the record
Coach approving an athlete's join requestIn the database: who approved, when, and which roster rowFor the life of the record

What we do not have is a user-visible audit trail inside the product. An administrator cannot today open a screen and read who viewed what. If that is a requirement for your institution, say so during evaluation rather than after.

Data retention

Program data is kept for as long as the account is active, because a coach's value in Forge is the multi-season history. There is no automatic expiry.

Vulnerability and patch management

The attack surface is deliberately small: static pages, serverless functions, and one third-party library in the browser.

What we do not have is a scheduled third-party vulnerability scan or a formal patch SLA. For an application of this shape, the honest control is the small surface plus the release gate, and we would rather describe that than claim a process we do not run.

What we do not have

Stated plainly rather than left for a questionnaire to uncover:

Questions, or a data privacy agreement you need signed? Email aaron@forgeathleticsystems.com. We would rather sign yours than ask you to accept ours.

Privacy Policy  ·  Terms of Service  ·  Home