This page provides evidence of controls implemented in PCS DMS to satisfy 21 CFR Part 11 (Electronic Records; Electronic Signatures) and EU GMP Annex 11. Auditors and inspectors may access this page without authentication. Live row counts are pulled from the production database at page render time.
| § | Requirement | Evidence / Control | Code Reference |
|---|---|---|---|
11.10(a) |
Validation | IQ/OQ/PQ validation pack completed prior to go-live. Validation summary report,
functional specification, risk assessment, and test scripts are maintained in
docs/validation/. |
docs/validation/08-validation-summary-report.md |
11.10(b) |
Accurate & complete copies | Every document transition to Effective state creates a frozen revision row capturing the exact file SHA-256, version, and effective date. 11 active documents tracked. | documentmaster_revision tableDocument::transition() |
11.10(c) |
Record protection | All records stored in MySQL InnoDB with daily backups. Sync queue provides an immutable log of every data change (append-only by design). | dms_sync_queue (view
— 182 rows) |
11.10(d) |
Limit system access | All protected routes require Auth::requireLogin().
Inactive accounts (active='N') are rejected at Auth::attempt().
Admin functions gated by Auth::requireAdmin() (priv_admin=Y). |
app/Lib/Auth.php |
11.10(e) |
Audit trail | Append-only sync queue records every INSERT/UPDATE with table, PK, action, and payload. Cannot be modified retroactively. 182 rows | dms_sync_queueapp/Lib/SyncEnqueuer.php |
11.10(f) |
Sequence enforcement | Document lifecycle matrix enforces legal next-states only:
Draft→In Review→Approved→Effective→Periodic Review/Superseded/Obsolete.
Any out-of-sequence transition throws InvalidArgumentException.
Same matrix applied to Change Control Requests. |
Document::transition()ChangeControl::transition() |
11.10(g) |
Authority checks | Auth::requireAdmin() gates: DocType deactivation,
Workflow definition create/update/deactivate, all AdminController endpoints,
password reset issuance. Regular users cannot perform these actions (HTTP 403). |
DocumentTypeController::deactivate()WorkflowController::store/update/deactivate()AdminController |
11.10(k) |
Document controls | Validation documentation pack including functional specification, risk assessment, IQ, OQ, and validation summary report. | docs/validation/README.md |
| § | Requirement | Evidence / Control | Code Reference |
|---|---|---|---|
11.50(a) |
Signature manifestations | Every e-signature record captures: signer login (name), timestamp, meaning (natural-language statement of intent), and IP address. 33 signatures recorded | dms_esignatureapp/Models/ESignature.php |
11.70 |
Signature / record linking | Each dms_esignature row stores TableName and
PrimaryKey linking the signature irrevocably to the signed record.
Deletions of signature rows are blocked by application logic. |
dms_esignature.TableNamedms_esignature.PrimaryKey |
| § | Requirement | Evidence / Control | Code Reference |
|---|---|---|---|
11.100(a) |
Unique to one individual | sec_users.login is the PRIMARY KEY — guaranteed unique per person.
No sharing of credentials permitted by policy (ALCOA principle). |
sec_users table (PK: login) |
11.100(c) |
Legally binding consent | On first authenticated session, every user is redirected to /consent
and must accept the statement: "my electronic signature within PCS DMS is the
legally binding equivalent of my handwritten signature."
Acceptance is logged with timestamp, IP, and user-agent.
6 consents recorded |
dms_signature_consentapp/Lib/Consent.phpAuth::requireLogin() |
| § | Requirement | Evidence / Control | Code Reference |
|---|---|---|---|
11.200(a)(1) |
At least two distinct components | Authentication uses login (identification component) + password (authenticator component). Both required — missing either returns a login failure. | Auth::attempt()LoginController::handleLogin() |
11.200(a)(2) |
First signing in session uses both components | Every document and CCR transition requires re-entry of the user's password
(password field on transition forms) verified via Auth::attempt()
before the e-signature is recorded. |
Document::transition()ChangeControl::transition()Transition view forms |
| § | Requirement | Evidence / Control | Code Reference |
|---|---|---|---|
11.300(a) |
Unique ID codes | sec_users.login is a PRIMARY KEY. The system rejects duplicate
logins at the database constraint level. Each login unambiguously identifies
one individual. |
sec_users (PRIMARY KEY login) |
11.300(b) |
Periodic password change | Passwords expire after 90 days (pswdexpdt). Expiry is checked
at every login — expired users are redirected to /change-password
before reaching any controlled content. All changes recorded in
dms_password_history with reason, timestamp, and IP. |
sec_users.pswdexpdtAuth::passwordExpired()dms_password_history |
11.300(c) |
Loss management procedures | Users submit a reset request at /forgot-password which creates a
dms_password_reset row (Status=Pending). A QA Admin reviews
pending requests at /admin/password-resets and issues a system-
generated 12-char random temporary password. The user is forced to change
it immediately on next login (pswdfstlogin=1). All steps logged.
3 reset requests total |
dms_password_resetAdminController::issueTempPassword()/admin/password-resets |
11.300(d) |
Transaction safeguards | CSRF tokens on all state-changing POSTs. APCu-based login throttle (5 attempts per IP / 10 per login before lockout). IP address logged on every login, consent acceptance, password change, and reset issuance. | app/Lib/Csrf.phpLoginController throttle methodsapp/Lib/Logger.php |
PCS DMS v1.0 · © 2026 Progen Chemicals Synthesis (PCS) India · System Info · Login