1. One-page summary
Our honest current state, as of 2026-07-02: horsenose is an early-stage product run by a solo operator. We do NOT hold SOC 2 or ISO 27001 today, and we have not yet had an external penetration test. This page describes what we do, what we hold, what we do not yet have, and what is on the roadmap. We would rather tell you plainly where we stand than overstate it.
- Who we are. horsenose is software for running a riding school — scheduling lessons, tracking attendance and how riders paid, managing passes and gift vouchers, calculating instructor earnings, and giving a stable’s customers a view of their own bookings. It is operated by DF Daniel Fojcik, a Polish sole proprietorship (NIP 6472592229 / REGON 387798601, Marklowice), trading as Nose / horsenose.
- Our two roles. We are the data controller for our own account, analytics, and security data, and a data processor acting on each stable’s instructions for the rider/customer data that stable enters. The processor relationship is governed by our Data Processing Agreement (DPA). See §8.
- What we hold. Account email and optional profile name/phone; invitation email addresses; the operational records a stable enters about its riders (names, contacts, lesson participation, passes/vouchers, payment-tracking labels, free-text notes); bcrypt-hashed schedule PINs; SHA-256-hashed invitation tokens. We hold no payment-card or bank data and no health data. Full inventory in §2.
- What protects it. TLS everywhere with HSTS preload; encryption at rest (AES-256); database-enforced row-level security isolating each stable; server-side session validation; step-up re-authentication for destructive and admin actions; a strict Content Security Policy; rate limiting and bot protection; and an append-only audit log. Full list in §4.
- Where it runs. EU by default — database, email, analytics, error monitoring, and the rate-limit store are hosted in the EEA. It is not 100% EEA: two edges (Cloudflare’s global network and optional Google sign-in in the US) sit outside it, covered by the EU-U.S. Data Privacy Framework and/or Standard Contractual Clauses. See §3.
- What we do not yet have. No SOC 2, ISO 27001, external penetration test, or bug-bounty programme. See §7. If your procurement process requires SOC 2 today, we are not yet the right fit.
- How to reach us about security. Email support@horsenose.eu with `Security` in the subject line. See §6 and §9.
2. Data we hold
We collect the minimum needed to run the Service. The categories below are the personal data that touches horsenose.
| Category | What it is | Our role | Where it lives |
|---|---|---|---|
| Account identity | Sign-in email address; authentication metadata (passwordless — email magic link, or optional Google sign-in identifier). No passwords are stored. | Controller | Supabase Auth (EU) |
| Profile data | Display name; optional phone number; locale/timezone | Controller (account-holders) | Supabase (EU) |
| Invitation data | The email address a stable invites; the invitation is carried by a single-use token stored only as a SHA-256 hash (the raw token is never persisted) | Processor (on the stable’s behalf) | Supabase (EU) |
| Rider / operational data a stable enters | Rider and customer names and contacts; which lessons they were scheduled for and attended; passes and gift vouchers issued, redeemed, or refunded; payment-method labels (cash / pass / voucher / BLIK) recording that a rider paid; one-way announcements (subject and body); free-text notes on passes, payments, and horses | Processor (the stable is the controller) | Supabase (EU) |
| Schedule PINs | Optional PIN protecting a stable’s public schedule, stored as a bcrypt hash (not reversible) | Processor | Supabase (EU) |
| Usage & technical data | IP address (rate limiting, abuse prevention, security); browser/OS/device; pages visited | Controller | Vercel logs (EU); Upstash counters; Cloudflare |
| Error/diagnostic data | Crash and error traces, with personal data scrubbed before send (see §4) | Controller | Sentry (EU data region) |
| Product analytics (consent-gated) | Pseudonymous identifier, events, pages, device/browser, approximate location; optionally a masked session recording (all on-screen text and inputs masked) — loaded only if you accept the cookie banner | Controller | PostHog EU Cloud |
What we do not hold
- No payment-card or bank data. We do not process riders’ payments. "Cash", "pass", "voucher", and "BLIK" are tracking labels a stable records — not transactions horsenose runs. Subscription billing (the fee a stable pays for horsenose) is live, but card data is handled entirely on the payment provider’s hosted checkout — Stripe for Polish stables, Dodo Payments (Merchant of Record) for non-Polish stables — and never reaches us, so we remain out of scope for PCI DSS (§8).
- No identity documents or addresses. We do not collect home addresses, ID-document numbers, or government identifiers.
- No special-category (health) data. We do not intend to collect Article 9 GDPR data and the product is not designed to store it. Stables are instructed (in the DPA) not to enter special-category data into free-text fields. Notes about a horse are about an animal, not a person, and fall outside GDPR.
- No advertising profiles, retargeting identifiers, or cross-site tracking. No Meta/LinkedIn/X/TikTok pixels; no browser fingerprinting.
- No data sold, rented, or loaned to third parties.
- No training of AI/ML models on your data. We do not train, fine-tune, or evaluate any AI or machine-learning model on personal data drawn from horsenose. The `pgvector` extension is enabled in our Postgres for future internal-search use cases but is not, today, populated with any personal-data-derived embeddings.
3. Infrastructure — who runs what, and where
horsenose is a Next.js application hosted on Vercel, backed by a Supabase Postgres database, with a small set of specialised providers ("sub-processors") each handling a narrow slice. None has end-to-end access to everything. Our default is the EU, and we say so honestly: the database, email, product analytics, and error monitoring all run in the EEA. It is not 100% EEA — a few edges sit outside it, covered by the EU-U.S. Data Privacy Framework and/or Standard Contractual Clauses (SCCs). We will not publish an unqualified "all data stays in the EU" claim while that is true.
| Provider | Role | Region |
|---|---|---|
| Supabase Inc. | Application database, authentication, file storage | EU — eu-central-1 (Frankfurt) |
| Vercel Inc. | Hosting, serverless compute, cron | EU — fra1 primary; global edge network |
| Brevo (Sendinblue SAS) | Transactional + magic-link email | EU (France) |
| PostHog Inc. (consent-gated) | Product analytics; masked session recording | EU Cloud (eu.posthog.com) |
| Sentry (Functional Software, Inc.) | Error monitoring | EU (data storage region) |
| Upstash, Inc. | Rate-limit counters + idempotency keys (IP-derived) | EU — Regional database in eu-central-1 (Frankfurt, AWS); no cross-region replication |
| Cloudflare, Inc. | Turnstile bot protection, DNS, CDN edge | Global edge (DPF + SCCs) |
| Google LLC (optional sign-in only) | Returns a persistent account identifier on Google sign-in | United States (EU-U.S. DPF + SCCs fallback) |
| Stripe Payments Europe, Ltd. | Subscription billing for Polish stables (PLN); horsenose is invoice issuer (faktura) | EU + US |
| Dodo Payments (Merchant of Record) | Legal seller of the subscription for non-Polish stables (EUR/GBP/USD); issues the tax-compliant invoice + calculates/remits VAT/sales tax | Global (MoR) |
The canonical, always-current version of this table — with per-provider personal-data categories and transfer mechanisms — is maintained on the Sub-processors page; the Privacy Policy and the DPA link to the same source rather than keeping divergent copies.
4. Technical measures
These are the controls actually in place today. (Controls we have not yet built are listed separately in §7 — we do not present planned measures as current.) This is also the substance that feeds Annex II (technical and organisational measures) of our DPA.
Network and transport
- TLS for all traffic, enforced by Vercel and Supabase. HSTS is set with `max-age=63072000; includeSubDomains; preload`.
- No mixed content — the Content Security Policy rejects `http://` resources.
Tenant isolation and authorisation
- Row-Level Security (RLS) scoped to each stable on every operational table, enforced in the database itself — one stable’s data cannot be read by another even if application code had a bug. This is the primary cross-tenant defence.
- Application-layer role gates (authenticated / stable-scoped / instructor-or-admin / super-admin) as defence-in-depth on top of RLS, never as the only line.
- Route-layer checks require an active session for protected paths and super-admin status for the admin surface.
Authentication
- Passwordless sign-in — email magic link (handled by Supabase Auth) or optional Google sign-in (OAuth). No passwords are stored.
- Server-side session validation on every protected request — the sign-in cookie alone is never trusted.
- Step-up re-authentication for destructive and administrative actions — a short-lived, separately-signed step-up cookie is required for operations such as account deletion, last-admin role changes, bulk deactivation, stable archival, and all super-admin writes; missing or expired step-up fails closed.
- The platform-admin surface returns 404 when no super-admin is configured, so its existence is not leaked.
Secrets and credential handling
- Schedule PINs are stored as bcrypt hashes; invitation tokens are stored as SHA-256 hashes — single-use, time-limited (7-day expiry), and email-bound; raw tokens are never persisted.
- The database service-role key is server-only — it is never bundled into client JavaScript; a build-time validator fails the build if a sensitive variable is mis-prefixed.
Input and output handling
- Schema validation at every server input boundary — client-side validation is treated as UX only; the server is the trust boundary.
- A strict Content Security Policy with a per-request nonce, plus a locked-down security-header set (`X-Content-Type-Options`, `X-Frame-Options` / `frame-ancestors`, `Referrer-Policy`, cross-origin isolation headers, and a restrictive `Permissions-Policy`).
- Automatic output escaping; user-authored content is plain text at this stage.
Abuse and bot protection
- Rate limiting on sign-in, sign-up, magic-link, invitation-accept, export/erasure, and other sensitive endpoints (per-email, per-IP, per-user, or per-stable depending on the action; each policy is fail-open or fail-closed by design).
- Cloudflare Turnstile bot protection on the sign-in form, sign-up form, magic-link request, invitation-accept page, and public-schedule PIN entry.
Data at rest and audit trail
- Encryption at rest via Supabase (AES-256).
- An append-only audit log records security-relevant events (authentication, role and membership changes, financial events, exports, deletions). It is always written and is distinct from operational telemetry.
- Error monitoring with personal-data scrubbing — before any error is sent to Sentry, a custom scrubber drops email addresses, phone numbers, message bodies, notes, and any field that looks like a token. What remains is technical context plus a pseudonymous user UUID, the stable identifier, the locale, and the name of the failing operation.
Backups and recovery
- Supabase provides automated daily backups (7-day retention at the current tier; longer retention is planned as the Service matures). Vercel retains prior deployments for near-instant rollback of a bad release.
5. Organisational measures
- Solo operator. horsenose is run by one person (Daniel Fojcik). There are no employees with production access at this time. If that changes — for example, a contractor with production access is onboarded — this page will be updated and active stables notified.
- Production data stays on managed infrastructure. Production database dumps are not stored on local machines; local development uses a separate database with synthetic data.
- Least privilege for service accounts. The database service-role key is scoped to server-side use only; browser database access uses a limited key behind row-level security.
- Secrets management. Secrets live in the hosting provider’s environment configuration and a gitignored local file — never committed to the repository. Production secrets are not copied to local machines.
- Provider-side access logging. Administrative actions on our providers are logged by those providers; we review them on an ad-hoc basis.
- Confidentiality. Personnel (currently the proprietor) are bound to confidentiality regarding personal data processed through the Service, as reflected in the DPA.
- Change discipline. Code changes pass a strict type, lint, and automated-test gate before deploy, and database migrations are applied to a staging environment before production.
6. Incident response (72-hour breach notification)
Monitoring. Errors flow to Sentry (with the personal-data scrubbing described in §4); request-level diagnostics are available in hosting logs; an uptime monitor and error-rate alerting are part of the hardening baseline. The append-only audit log provides a durable record of security-relevant events for investigation.
Our breach-notification commitment. If a personal-data breach occurs that is likely to result in a risk to the rights and freedoms of affected individuals, we will:
- Notify the competent supervisory authority — the President of UODO in Poland — without undue delay and, where feasible, within 72 hours of becoming aware of the breach (Article 33 GDPR).
- *Where the breach is likely to result in a high* risk to affected individuals, notify them without undue delay, describing the nature of the breach, the categories of data involved, the likely consequences, and the measures taken (Article 34 GDPR**).
- Where we act as a processor for a stable, notify that stable (the controller) without undue delay so it can meet its own Article 33/34 obligations to its riders.
This mirrors the Privacy Policy and the DPA. It states how we intend to implement an obligation the GDPR already imposes — it is not an additional contractual promise beyond GDPR. A formally documented incident-response runbook is on the roadmap (§7); until then a one-person team responds ad hoc within the timelines above.
Contact. Non-urgent: support@horsenose.eu. Security (urgent): email support@horsenose.eu with `Security` in the subject line.
7. What we do not have yet — roadmap
This is the section that earns the rest of the page its credibility: we do not hide the gap. We are a small, early-stage operation, and several controls a larger buyer may expect are not yet in place.
| Item | Current state | Direction |
|---|---|---|
| SOC 2 (Type I / II) | Not started | Not before there is a team and a compliance budget; no committed date |
| ISO 27001 | Not started | Not planned in the first year |
| External penetration test | Not yet conducted | Planned as the Service matures toward broader paid use |
| Bug-bounty programme | None | Considered only after a first external penetration test |
| Staging environment | In place | Maintained |
| Automated dependency / security scanning in CI | Not yet — being added to the build pipeline | Added at MVP |
| Secret rotation | Manual today | Documented runbook at MVP; scheduled (e.g. quarterly) rotation as the team grows |
| Formally documented incident-response process | Not yet — handled ad hoc within the 72-hour commitment (§6) | Documented runbook as the Service matures |
| Dedicated `security@` address / PGP key | Not yet — use support@horsenose.eu with `Security` in the subject | Planned |
| Continuous compliance monitoring | Not yet | Paired with any future SOC 2 work |
If a prospective stable’s procurement flow requires SOC 2 today, we are not currently the right fit — and we will say so honestly rather than stall the conversation.
8. Compliance framing
GDPR (Regulation 2016/679). horsenose operates under a dual role: controller for the data whose purposes and means it determines (marketing-site visitors, the account/contact data of stable administrators and instructors, consent-gated product analytics, and security/abuse-prevention data), and processor for the rider/customer operational data a stable enters — there, the stable is the controller and horsenose processes on the stable’s documented instructions under the DPA (Article 28 GDPR). Sub-processors operate under Article 28 contracts (DPA + SCCs/DPF where a transfer leaves the EEA) — see the Sub-processors page.
Children’s data. Riding schools regularly teach children, so horsenose knowingly processes minors’ data on a stable’s behalf (for example, a child entered as a lesson participant, often by a parent who is the stable’s customer). The stable is responsible for the lawful basis and any parental consent or authority required (Article 8 GDPR); horsenose minimises what is held about a child and does not target or market to children directly. See Privacy Policy §11.
Data-subject rights are supported, including self-service access/portability via a JSON export at /account/export and erasure via /account/delete (a 30-day reversible grace period and step-up re-authentication apply; on erasure we strip direct identifiers rather than hard-delete — pseudonymisation under Art. 4(5) GDPR, not full anonymisation under Recital 26; see Privacy Policy §8 for the field-level detail). For rider data the controller is the stable, so a rider exercises rights against their stable and horsenose assists as processor.
PCI DSS — not applicable. We do not handle, store, or transmit card data; cash/pass/voucher/BLIK are tracking labels (§2). For subscription billing, the card-data path is carried entirely by the payment provider on its hosted checkout — Stripe (payment processor) for Polish stables, with horsenose as merchant, and Dodo Payments as Merchant of Record for non-Polish stables — so horsenose never receives card data and remains out of PCI scope.
EU AI Act — not applicable. horsenose is an operations tool for riding schools; it does not train, develop, or deploy AI models, and no component uses machine-learning or generative AI to process personal data. The `pgvector` Postgres extension is enabled for possible future internal-search use cases but is not populated with personal-data-derived embeddings today; if that changes, we will publish an EU AI Act position and a "no training on personal data" commitment before the feature ships.
ePrivacy / cookies. Optional analytics (PostHog, including masked session recording) load only on consent; strictly-necessary cookies are exempt under Article 5(3) of the ePrivacy Directive. See the Cookie Policy.
9. Responsible disclosure
If you believe you have found a security vulnerability in horsenose:
- Email [support@horsenose.eu](mailto:support@horsenose.eu) with `Security` in the subject line. (A dedicated `security@` address and a PGP key are planned — §7.)
- Include enough detail to reproduce the issue.
- Give us a reasonable period to investigate and remediate before any public disclosure.
What you can expect from us:
- An acknowledgement and an initial assessment as soon as reasonably practicable. horsenose is a solo-operated service and cannot guarantee a same-day reply; we will not let a credible report sit unattended.
- Status updates at reasonable intervals while the issue is being triaged or fixed.
- Credit in any post-fix disclosure, if you would like it (optional).
What we cannot yet offer: we do not pay monetary bug bounties at this stage. We will say so clearly if and when a bounty programme becomes available.
Scope and safe harbour. Good-faith security research that follows this policy, stays within your own accounts, avoids degrading the Service for others, and does not access data other than your own will not be treated as a violation of our Acceptable Use Policy or Terms of Service. Do not attempt to access another stable’s or another rider’s data, and do not run automated scraping or denial-of-service testing against the Service.
10. Change log
| Date | Change |
|---|---|
| 2026-07-02 | Subscription billing reconciled as live (Stripe for Polish stables; Dodo Payments as Merchant of Record for non-Polish stables); Upstash recorded as Regional EU-only (Frankfurt) throughout. |
| 2026-05-23 | Initial publication (in-house draft; counsel review pending). |