Project WorkProject WorkSign in

Legal

Security Practices

Q Lighting Co., Ltd. · Last updated: 13 May 2026

Overview

Our Commitment to Security

Q Lighting Co., Ltd. takes the security of Project Work and the data entrusted to it seriously. This document describes the security measures, architectural controls, and operational practices in place to protect the Platform and its users.

Project Work is a multi-tenant SaaS platform handling sensitive project documents and client approval records for design and construction firms. Security is a core requirement of the product, not an afterthought.

01

Authentication

1.1 OAuth Only — No Passwords Stored

Project Work does not store passwords. All authentication is handled via OAuth 2.0 through Google or Microsoft (Azure Entra ID). Credentials are managed entirely by those providers and are never transmitted to or stored by the Platform.

1.2 Provider Identity Verification

At sign-in, the Platform receives a verified identity token from Google or Microsoft. The token includes the user's email address and a stable, provider-issued unique identifier (OAuth sub). The Platform stores the OAuth provider name and sub to uniquely identify each account, independent of email changes.

1.3 Session Management

Sessions are managed using JSON Web Tokens (JWT) via Auth.js. Tokens are signed with a strong secret key and are not stored server-side. JWTs are rotated on each authentication event.

Client sessions are checked every 60 seconds to detect if a client account has been promoted to staff status, ensuring that access rights are updated promptly without requiring re-authentication.

1.4 Session Routing by Account Type

Upon successful authentication, the backend determines the user's account type (tenant staff, client, or super administrator) and routes them to the correct workspace. Users do not select their role at sign-in. This prevents role spoofing at the entry point.

02

Tenant Isolation

2.1 Strict Multi-Tenant Architecture

Each company ("tenant") using the Platform operates in a fully isolated workspace. Data belonging to one tenant is never visible to or accessible by another tenant.

2.2 Server-Side Tenant Context Derivation

The tenant identity of every authenticated staff session is derived exclusively from the authenticated session on the server side. APIs do not accept or trust a tenant identifier supplied in a request body, query string, or header. This prevents cross-tenant attacks via request manipulation.

2.3 PostgreSQL Row-Level Security (RLS)

Tenant isolation is enforced at the database layer using PostgreSQL Row-Level Security policies. Every tenant-scoped table carries a non-nullable tenant_id column. RLS policies verify that the session's tenant context matches each row before any read or write operation is permitted.

A session-level variable (app.tenant_id) is set at the start of every database transaction for staff operations. The database enforces isolation even if application-level checks were somehow bypassed.

For client sessions, RLS policies verify project-level access through the project_client_access table rather than by tenant ID, reflecting the fact that clients may access projects across multiple tenants from a single account.

All 16 tenant-scoped tables have both ENABLE ROW LEVEL SECURITY and FORCE ROW LEVEL SECURITY set, ensuring policies apply even to the table owner role.

2.4 File Storage Isolation

PDF revision files are stored on the server filesystem under a path structure that uses database-assigned UUIDs only:

/tenants/{tenant_id}/projects/{project_id}/revisions/{revision_id}.pdf

No user-supplied names or labels appear in file paths. The application enforces that the path prefix matches the authenticated tenant before any file is read or written, preventing path traversal attacks and cross-tenant file access.

03

Access Control

3.1 Role-Based Permissions

Within each tenant workspace, access to sensitive operations is controlled by a configurable role and permission system. Roles include Tenant Administrator, Team Head, and Designer. Each role has a defined set of permitted actions, and these are enforced server-side on every API request.

The permission set is tenant-configurable (e.g. whether Team Heads may release revisions to clients), but the Tenant Administrator role always retains full access and the permission grid itself can only be modified by a Tenant Administrator.

3.2 Client Access Controls

Clients can only access projects they have been explicitly invited to. Access is tracked in the project_client_access table and enforced at both application and database levels. A client who is removed or whose access is revoked immediately loses access to that project.

Clients can only see revisions that have been formally released to them. Internal revisions (in WORKING, INTERNAL_REVIEW, or INTERNAL_APPROVED status) and internal staff comments are never visible to client sessions.

3.3 Super Administrator Isolation

The Super Administrator area is a separate, elevated access level reserved for Q Lighting Co., Ltd. platform operators. Super administrators are stored in a separate table (super_admins) and operate outside the tenant system. Super admin routes are protected by separate middleware and session checks.

04

Invitation Security

Project invitations to clients can be issued via three methods: email invitation, shareable link, or access code.

  • Invitation tokens (used in shareable links) and access codes are generated as cryptographically random values.
  • Only the cryptographic hash of each token or code is stored in the database. The plaintext value is never stored and cannot be recovered from the database.
  • Tokens are time-limited and have an expiry date.
  • Each token is single-use. Once claimed by a client, it is deactivated.
  • The claim process verifies the token hash against stored hashes using a secure comparison.

05

Audit Trail Integrity

5.1 Append-Only Client Action Log

Every action taken by a client — viewing a revision, leaving a comment, approving, or rejecting — is recorded in the client_actions table. This table is designed to be append-only:

  • UPDATE and DELETE operations on client_actions are prevented by database triggers that raise an exception regardless of the requesting role.
  • The audit trail cannot be modified, backdated, or erased through the application layer.

This design ensures that approval and rejection records are tamper-evident and can be relied upon as a permanent record of client decisions.

5.2 Revision Workflow Integrity

Revision status transitions are enforced by a database trigger. A revision can only advance through defined stages (e.g. WORKING → INTERNAL_REVIEW → INTERNAL_APPROVED → RELEASED_TO_CLIENT). Skipping stages or reversing to an earlier status is rejected at the database level, independent of application logic.

5.3 Electronic Signature Records

When a client e-signature is collected on approval, the signature image and associated metadata (client ID, revision ID, timestamp) are stored permanently. These records form part of the audit trail for finalized revisions.

06

Data in Transit

All communication between users and the Platform is encrypted using HTTPS/TLS. The Platform is served exclusively over HTTPS, enforced by the Traefik reverse proxy. Unencrypted HTTP requests are redirected to HTTPS.

Email notifications are delivered via an SMTP relay (Brevo) using TLS-secured connections.

07

Data at Rest

PDF revision files are stored on an encrypted-at-rest filesystem on the Platform's hosting infrastructure (Hetzner Cloud). Database data is stored in PostgreSQL on the same infrastructure.

Sensitive tokens (invitation links, access codes) are stored only as cryptographic hashes — the cleartext value is never written to persistent storage.

08

Infrastructure and Deployment

8.1 Hosting

The Platform is hosted on Hetzner Cloud infrastructure. The application runs as a containerised service managed by Docker Swarm. Traffic is routed and terminated by Traefik, which handles TLS certificate provisioning and renewal.

8.2 Secrets Management

Production secrets (database credentials, OAuth keys, SMTP credentials, session signing keys) are managed as Docker Swarm secrets or environment variables and are never committed to source control. The application's repository contains only example variable names, not values.

8.3 Immutable Deployments

New versions of the application are deployed using immutable Docker image tags based on the Git commit hash. Deployments update the running service image without in-place modification of running containers.

8.4 Cron Endpoint Protection

The reminder cron endpoint (/api/cron/reminders) is protected by a shared secret passed in a request header (CRON_SECRET). Requests without the correct secret are rejected before any processing occurs.

09

Error Monitoring

Application errors and performance issues are monitored using Sentry, covering client-side, server-side, and edge runtime errors. Error reports may contain stack traces and contextual information. Sentry is configured to capture exceptions and to help diagnose production issues promptly.

Personal data included in error payloads is subject to Sentry's data processing terms. We configure Sentry to minimise the capture of unnecessary personal data.

10

Internal Data Separation

Staff-only data (internal review comments, workflow notes) is stored in a dedicated table (internal_comments) that is completely separate from client-facing action records. Database RLS policies and application-layer access controls both enforce that client sessions can never read internal comments, regardless of how the request is constructed.

11

Third-Party Services

The Platform uses the following third-party services, each of which may process limited data:

ServicePurpose
Google OAuthAuthentication for users with Google accounts
Microsoft OAuthAuthentication for users with Microsoft accounts
BrevoTransactional email delivery
SentryError monitoring and performance tracking
Hetzner CloudInfrastructure hosting

No third-party advertising networks, behavioural analytics, or data brokers are used.

12

Vulnerability Disclosure

If you discover a security vulnerability in Project Work, please report it responsibly to us before public disclosure. We are committed to investigating all reported issues promptly and to communicating our findings and remediation timeline.

To report a vulnerability, contact us at:

Email: project@quill-shop.com

Subject: Security Vulnerability Report — Project Work

Please include a description of the issue, steps to reproduce, and the potential impact. We ask that you:

  • Not access, modify, or delete data belonging to other users.
  • Not perform actions that could disrupt service availability.
  • Allow us reasonable time to investigate and remediate before any public disclosure.

We treat all responsible disclosures with seriousness and appreciate the effort of the security research community in helping keep the Platform safe.

13

Contact

For security-related enquiries, please contact:

Q Lighting Co., Ltd.

Kingdom of Thailand

Email: project@quill-shop.com

© 2026 ProjectWork by Q Lighting. All rights reserved.

  • Privacy
  • Terms
  • Security
  • Sign in