Commit Graph

33 Commits

Author SHA1 Message Date
Bryan Frimin
0f0f6643ad Rename backend services for portal
Point domain services, bootstrap, and related
packages at Compliance Portal types so callers
stop depending on the old Trust Center names.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:24 +02:00
Sacha Al Himdani
4c57d201a4 Make license declarations consistently MIT
The source headers, LICENSE files, and license metadata had drifted
apart. Align the entire project to MIT:

- Convert every source-file header to the MIT text across all comment
  styles (Go, TS, TSX, JS, MJS, SQL, CSS, GraphQL, shell), including
  SPDX-License-Identifier tags
- Set the root and cookie-banner LICENSE files to the MIT text with a
  "MIT License" title line
- Switch the package.json license fields, Docker image label, and
  cookie-banner README to MIT
- Update docs and the genmodels header generator accordingly
- Normalize copyright lines to a single format
  (Copyright (c) <year(s)> Probo Inc <hello@probo.com>.): unify the
  hello@getprobo.com and hello@probo.inc emails to hello@probo.com and
  the comma-separated years to a hyphenated range

Genuine third-party references are intentionally left untouched: the
Lucide icon attributions (Lucide is ISC) and the trivy dependency
license allowlist.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-13 16:21:14 +02:00
Bryan Frimin
f20c3d73d2 Verify signature ownership in esign accept/record-event flows
Any self-provisioned trust center visitor could accept another
visitor's NDA signature or inject audit-trail events into it by
supplying its GID, since AcceptSignature and RecordEvent trusted the
client-supplied signature ID without checking it belonged to the
caller (GHSA-22xj-f767-ppw6). SignerEmail/ActorEmail are always
derived from the verified session identity, never client input, so
comparing them against the signature's stored SignerEmail in
pkg/esign/service.go closes the hole at its root without touching the
resolver-level authorization already in place elsewhere.

Adds an e2e regression test that self-provisions two trust center
visitors through the real magic-link flow and confirms one cannot
touch the other's signature.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-09 10:27:22 +02:00
Sacha Al Himdani
180a6a0420 Confine trust center reads and signatures to the page's tenant
The public trust API derived its authorization scope from client-supplied
global IDs, so a visitor on one trust center could resolve nodes, export
audit-report PDFs, and read or mutate electronic signatures belonging to
another organization (cross-tenant access).

Every trust API resolver now derives its scope from the active compliance
page's organization via compliancepage.ScopeFromContext, so reads are always
confined to the page's tenant. Cross-tenant or unknown IDs surface as
not-found instead of leaking data or returning a 500. Active/presence is
enforced upstream by the id and presence middlewares.

esign's signature operations (GetSignatureByID, AcceptSignature, RecordEvent)
now take a caller-provided scope instead of deriving one from the requested
ID, so signature reads and mutations are tenant-scoped at the source. This
removes the need for a resolver-level authorization helper; RecordEvent also
verifies signature ownership within scope before recording, since the event
foreign key is not tenant-composite.

Adds e2e non-regression tests covering owning vs. foreign trust center report
export and the generic node(id:) resolver.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-06 18:59:41 +02:00
Sacha Al Himdani
bf20ca1a90 Add esign to document signatures
Employee document signatures recorded an acknowledgment with no
cryptographic proof, unlike document approvals which already create
and accept an electronic signature on every decision.

Mirror the approval flow on the sign path: generate the signed
document PDF, create-and-accept an esign record, and persist its id
on the document_version_signatures row through a new
electronic_signature_id column. Capture the signer IP and user agent
in the resolver, and re-check the published/archived preconditions
inside the transaction so the seal cannot race document state.

Make the consent wording a single backend source of truth shared by
the text that is sealed and the text shown in the UI. Define
DocumentSignatureConsentText and DocumentApprovalConsentText in the
probo service package and the NDA copy in the trust service, each
owned by the flow that uses it, and stop esign from appending the
generic clause to caller-provided consent text so approvals no
longer seal a duplicated sentence.

Expose the resolved consent text through GraphQL on
EmployeeDocumentVersion and DocumentVersionApprovalDecision, and have
the signing, approval, and NDA pages render it from the API instead
of hard-coded strings, mirroring how the NDA page already worked.

Align the wording with the actual interaction: the buttons read
"Review and sign" and "Review and approve", the clauses reference
those actions, and the inaccurate "typing my full name" phrasing is
removed everywhere.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-15 19:18:42 +02:00
Ludovic Vielle
eccef41767 Adopt File type for trust logos and MCP
Trust GraphQL and MCP still exposed presigned URL strings for
trust-center logos while console and connect already serve stable
File.downloadUrl paths. Phase 1 migrates the seven public logo
fields on trust GraphQL and the trust-center file references on MCP
to the shared File type; trust GraphQL NDA stays on fileUrl for a
follow-up.

Trust resolvers load public files through filemanager and map them
with types.NewFile. The trust app Relay queries and components now
read logo.downloadUrl. MCP specification, resolvers, and helpers
are updated in sync, including NDA on MCP where callers already
have file access.

filemanager is split into focused files and its URL surface is
narrowed to GenerateFileURL(file) for stable app URLs and
GeneratePresignedURL for S3 redirects. GetPublicFile remains the
DB entry point when only a file ID is known.

Add trust and MCP e2e coverage for public logo download URLs.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-11 16:03:45 +02:00
Sacha Al Himdani
c7e2fc209f Use probo.com for bare and marketing domain references
Replace the bare `getprobo.com` domain and the `www.getprobo.com`
marketing host with `probo.com` / `www.probo.com` across the codebase.
Functional subdomains (app, console, notification, custom, test,
cookie-banner, compliance) keep their existing `getprobo.com` hosts,
and changelog entries are left untouched.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-11 13:46:10 +02:00
Ludovic Vielle
b679107fa5 Migrate all callers to unified filemanager.Service
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-10 15:53:32 +02:00
Ludovic Vielle
60435f277b Serve brand assets as static files via /api/files/v1/static instead of S3
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-09 17:42:18 +02:00
Sacha Al Himdani
9ac71f948f Update contact email to hello@probo.com
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-09 16:45:23 +02:00
Sacha Al Himdani
6948a6b9ab Tailor signature certificate email copy for approvals
Store the per-signature email subject as text on the electronic_signatures
row at creation time, mirroring the consent_text pattern. The document
approval service sets "Your approved <Title> - Certificate of Completion";
other callers default to "Your signed <Name> - Certificate of Completion".
The certificate worker uses signature.email_subject as the email subject,
falling back to the default format when the column is empty.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-05-21 14:49:19 +02:00
Émile Ré
f5703d390b Enforce Go style rules across codebase
Apply five style rules: convert iota string enums to typed
string constants, replace errors.As with errors.AsType,
merge three-group imports into two groups, fix multiline
parameter/argument formatting, and replace fmt.Sprintf URL
construction with net/url.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-20 11:46:39 +04:00
Émile Ré
9156d6a16a Add wsl linter and fix
Signed-off-by: Émile Ré <emile@probo.com>
2026-05-20 09:27:28 +04:00
Bryan Frimin
43336078f4 Migrate workers to kit/worker
Replace hand-rolled polling loops, semaphores, and WaitGroups
in all 7 background workers with go.gearno.de/kit/worker. Each
worker now implements Handler[T] (Claim/Process) and optionally
StaleRecoverer, gaining automatic Prometheus metrics and
OpenTelemetry tracing. Bumps kit from v0.3.0 to v0.5.0.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-13 12:25:42 +02:00
Bryan Frimin
f17fb7bf49 Upgrade to kit v0.3.0
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-03 11:56:06 +02:00
Sacha Al Himdani
999171a626 Add document approval workflow
Introduce a complete approval system for document publishing. Document
versions can now require approval from selected reviewers before being
published, with automatic publishing once all approvers have approved.

- Add approval quorum and decision tables with backfill migration
- Implement request approval, approve, and reject flows with electronic
  signature support for approve decisions
- Add employee approvals page with dedicated tab and pending approvals view
- Add changelog field to publish and request approval flows
- Pre-select previous version's approvers in the publish dialog
- Show quorum approvers in document list with 100 approver hard limit
- Expose approval workflow through GraphQL, MCP, and CLI
- Remove legacy default approvers feature entirely
- Add comprehensive e2e test coverage for approval workflows

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-27 19:43:20 +01:00
Sacha Al Himdani
8c02c53315 Update copyright headers across all Go files
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-25 17:38:32 +01:00
Bryan Frimin
2f8edfb6be Add per-email sender name for compliance page emails
When an email has a sender name set (the organization name), the
mailer composes the From header as "OrgName via Probo" instead of
the default global sender name. This gives compliance page
recipients clearer context about which organization is contacting
them.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-22 10:56:51 +01:00
Bryan Frimin
a5743729f7 Add file visibility (PRIVATE/PUBLIC) + public files API
Adds a visibility enum to files with PRIVATE (default) and PUBLIC states.
PUBLIC files are accessible via an unauthenticated /api/files/v1/{fileID}
endpoint that redirects to a presigned S3 URL. Introduces pkg/file service
to manage file operations. Logo uploads (trust centers, organizations,
frameworks, references) are marked PUBLIC; other files are PRIVATE.
Includes database migration and backfill for existing logos.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-18 19:19:04 +01:00
Sacha Al Himdani
16b966b8fb Fix multiline function call style violations
Expand mixed inline/multiline function calls so each argument
is on its own line, matching the one-argument-per-line rule.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-17 15:59:26 +01:00
Sacha Al Himdani
85ec106cd6 Send mailing list emails
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-11 15:34:37 +01:00
Émile Ré
9da8cc2e3d Add nda signature middleware
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-03-03 22:07:01 +04:00
Sacha Al Himdani
21ed4113c3 Go format
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-03 11:17:05 +01:00
Bryan Frimin
9ec950d633 Remove content type from email attachment
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:33 +01:00
Bryan Frimin
ef28350c63 Fix worker retry
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:32 +01:00
Bryan Frimin
091e341479 Fix no crash
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:31 +01:00
Bryan Frimin
28d0d435d2 Fix ctx cancel not listen
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:31 +01:00
Bryan Frimin
c8be45008f Fix otel span lost
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:30 +01:00
Bryan Frimin
877d793f80 Fix possible injection
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:30 +01:00
Bryan Frimin
33747c46eb Add file stamp
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:28 +01:00
Bryan Frimin
1f484fcab0 Style
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:28 +01:00
Bryan Frimin
16503a7df4 Use electronic signature for compliage page NDA
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:27 +01:00
Bryan Frimin
c191d25e9a Add electronic signature
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:27 +01:00