Independent and not affiliated with the FDA, MHRA, ISPE, PDA, or any agency. Get the appgoutham@madhadi.com
madhadi.comData Integrity & GxP Quality
Browse all topics → Articles Templates & Procedures Learning paths GlossaryScenariosToolsRegulatory ReferencesLearning PathsTopics About Start here
Specification Plug-and-play starting point AI & Automation

Specification: GxP Analytics Tool (Script, Notebook, Dashboard, or Query)

A plug-and-play requirements and design specification for a homegrown GxP analytics tool: intended use, input contract with types and ranges, the calculation stated explicitly with its equation and source method, outputs and the controlled result field, rounding rules, fail-loudly error handling, pinned environment, stated limits of validity, a per-measure section for low-code dashboards, numbered testable requirements, and a requirement-to-test traceability table.

Document type: Specification

Read and copy the template below into your own quality system. It is a generic starting point for your own internal use, provided as is, with no warranty; see the Terms and License. Adopting it does not by itself create compliance.

This is a ready-to-use specification for one analytics tool. It exists so that testing has a pass criterion: without a written statement of what the tool must do, “we tested it” means “we ran it and the output looked reasonable”. Replace every <<FILL: ...>> placeholder with your own specifics, set your document numbers and dates, and route it through your normal document control, review, and approval before testing begins. A worked filled specimen follows. This content is educational reference, not legal or regulatory advice; verify each cited regulation against the current source before you rely on it.

Document control header

FieldEntry
Document titleSpecification, <<FILL: tool name>>
Document number<<FILL: SPEC-ID>>
Version<<FILL>>
Effective date<<FILL>>
Tool ID<<FILL: from the analytics tool inventory register>>
Risk class<<FILL: A / B / C, from the risk classification record>>
Risk classification reference<<FILL: RC-YYYY-nnnn>>
Governing procedure<<FILL: SOP-ID>>
Author<<FILL>>
Supersedes<<FILL: prior version or "New">>

How to write requirements in this document

Every requirement carries a unique ID, is written so that a tester can observe pass or fail without interpretation, and states one thing. Use the prefixes below so that a traceability table sorts sensibly and a reader can see at a glance what a failing test threatens.

PrefixRequirement category
INInput contract: source, format, columns, types, units, ranges, missing and out-of-range handling
CALCProcessing logic and calculations
RNDRounding, precision, and significant figures
OUTOutputs, format, destination, and which field is the controlled result
ERRError handling and failure behaviour
ENVEnvironment and dependency requirements
SECAccess, security, and read-only behaviour toward the source
MEAPer-measure requirements for low-code dashboards
LIMStated limits of validity

Wording that is not testable: “the tool shall handle errors appropriately”, “performance shall be acceptable”, “results shall be accurate”. Wording that is testable: “on encountering a non-numeric value in the timepoint column, the tool shall write no output file and shall exit with a non-zero status and a message naming the offending row”.

1. Purpose and intended use

FieldEntry
One-sentence statement of what the tool produces<<FILL>>
The GxP decision the output supports<<FILL: name the decision and the record where it is taken>>
Who uses the output and in what role<<FILL>>
Frequency of use<<FILL>>
Is the output the record of origin or a view<<FILL>>
Source method, SOP, compendial procedure, or statistical method implemented<<FILL: name and version>>
What this tool explicitly does not do<<FILL>>

2. Inputs

2.1 Input sources

InputSource system and validation statusExtraction methodFormatRefresh or extraction timing
<<FILL>><<FILL>><<FILL: named export, read-only view, API, direct query>><<FILL>><<FILL>>

2.2 Input contract

State the expected schema exactly. A tool that accepts whatever it is given cannot be tested.

Column or fieldData typeUnitsRequiredAllowed range or valuesHandling of missingHandling of out of range
<<FILL>><<FILL>><<FILL>>Yes / No<<FILL>><<FILL: reject / impute with stated rule / exclude with logged reason>><<FILL>>

2.3 Input requirements

IDRequirement
IN-01The tool shall read only from <<FILL: named source>> and shall not accept a manually edited copy of that extract.
IN-02The tool shall verify that all columns listed in section 2.2 are present, and shall reject the input naming any missing column.
IN-03The tool shall verify the data type of each column against section 2.2 and shall reject the input naming the first offending row and column.
IN-04The tool shall reject input containing fewer than <<FILL: minimum record count>> records.
IN-05The tool shall record, in the output provenance block, an identifier or hash of the input dataset used.
IN-06<<FILL: additional input requirement>>

3. Processing logic and calculation

3.1 Narrative description

<<FILL: describe the processing in ordered steps, in plain language, so a reviewer who does not read code can follow what happens to the data from input to output>>

3.2 The calculation

State the equation where a calculation is performed. Where the method comes from a compendial procedure, a pharmacopoeial chapter, an SOP, or a statistical reference, name it and describe the method in your own words rather than reproducing the source text.

<<FILL: the equation, with every term defined and its units stated>>

Terms:

SymbolMeaningUnits
<<FILL>><<FILL>><<FILL>>

Source method implemented: <<FILL: name, version, and clause>>

3.3 Exclusion, filtering, and grouping rules

Any rule that removes or partitions data is a calculation and must be specified, because it is where results most often silently diverge from expectation.

RuleDefinitionJustificationRequirement ID
<<FILL: e.g. outlier exclusion>><<FILL: the exact test and threshold>><<FILL>><<FILL>>
<<FILL: e.g. date window>><<FILL: inclusive or exclusive at each end, and the time zone>><<FILL>><<FILL>>

3.4 Calculation requirements

IDRequirement
CALC-01<<FILL: the primary calculation, stated so it can be verified against an independent computation>>
CALC-02<<FILL>>
CALC-03The tool shall apply the exclusion rules in section 3.3 in the stated order and shall record in the output which records were excluded and under which rule.
CALC-04<<FILL: any conditional or branching logic, with the condition stated>>

4. Rounding and significant figures

Rounding is stated explicitly because it is a common source of silent disagreement between a homegrown tool and a validated source system, and because “the two systems round differently” is a finding that is trivially avoidable and frequently found.

ValueReported precisionRounding ruleStage at which rounding is applied
<<FILL>><<FILL: decimal places or significant figures>><<FILL: half-up, half-even, truncate>><<FILL: final reporting only, or intermediate>>
IDRequirement
RND-01Rounding shall be applied only at final reporting. All intermediate computation shall be carried at full available precision.
RND-02<<FILL: the reported value>> shall be reported to <<FILL: n>> decimal places using <<FILL: rounding rule>>.
RND-03The rounding rule shall match that used by <<FILL: named source or downstream system>>, and any difference shall be documented and justified here.

5. Outputs

5.1 Output definition

OutputFormatDestinationIs this the controlled resultConsumer
<<FILL>><<FILL>><<FILL>>Yes / No<<FILL>>

5.2 Output schema

FieldTypeUnitsPrecisionDescription
<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>>

5.3 Provenance block

Every GxP output carries a provenance block so that the result can be traced back to the exact logic and data that produced it.

ElementContent
Tool ID and name<<FILL>>
Version tag and commit identifier<<FILL>>
Environment identifier<<FILL: manifest reference or image digest>>
Run timestamp and time zone<<FILL>>
Operator or service account<<FILL>>
Input dataset identifier or hash<<FILL>>
Specification document and version<<FILL>>

5.4 Output requirements

IDRequirement
OUT-01The tool shall write the output to <<FILL: destination>> with the schema in section 5.2 and no additional or missing fields.
OUT-02The field <<FILL: name>> is the controlled result. All other fields are supporting.
OUT-03Every output shall carry the complete provenance block in section 5.3.
OUT-04The tool shall not overwrite a previous output. Outputs shall be written with a unique name or to a versioned location.
OUT-05<<FILL>>

6. Error handling

The governing rule is fail loudly. A GxP tool that cannot compute a correct answer must produce no answer, visibly, rather than a plausible wrong one.

ConditionRequired behaviourRequirement ID
Missing or unreadable input file<<FILL>>ERR-01
Missing required column<<FILL>>ERR-02
Wrong data type in a required column<<FILL>>ERR-03
Value outside the allowed range in section 2.2<<FILL>>ERR-04
Fewer records than the stated minimum<<FILL>>ERR-05
Division by zero or an undefined mathematical result<<FILL>>ERR-06
Loss of connection to the source during execution<<FILL>>ERR-07
Output destination not writable<<FILL>>ERR-08
IDRequirement
ERR-09In every failure condition the tool shall write no output file, or shall write an output clearly marked as failed that cannot be mistaken for a result.
ERR-10Every failure shall produce a message that names the condition and, where applicable, the offending record, and shall be recorded in the run log at <<FILL: log location>>.
ERR-11The tool shall not silently substitute a default value for a missing or invalid input.
ERR-12The tool shall exit with a non-zero status on failure so that a scheduling or orchestration layer detects the failure.

7. Environment and dependencies

IDRequirement
ENV-01The tool shall run on <<FILL: language and runtime version>>, pinned exactly.
ENV-02Every library dependency shall be pinned to an exact version in <<FILL: manifest filename>>, stored in version control with the code.
ENV-03The tool shall run in an isolated environment (<<FILL: virtual environment, package snapshot, or container image>>) on <<FILL: qualified infrastructure reference>>.
ENV-04The tool shall not require internet access at run time, or where it does, the accessed endpoint shall be named here and its availability treated as an input dependency.
ENV-05A change to any pinned version is a change requiring assessment and, where results could be affected, re-execution of the calculation test cases.

Pinned manifest:

<<FILL: exact runtime and library versions, one per line>>

8. Access and source protection

IDRequirement
SEC-01The tool shall connect to the source system with a read-only account and shall not write, update, or delete any record in the source.
SEC-02Permission to modify the tool shall be restricted to <<FILL: named group>> and shall be separate from permission to run it.
SEC-03Credentials shall be retrieved at run time from <<FILL: secrets solution>> and shall not appear in the code, the manifest, the output, or the logs.
SEC-04<<FILL: row-level or record-level access requirements, if any>>

9. For low-code dashboards: per-measure specification

Complete this section instead of, or in addition to, sections 3 to 5 where the tool is a dashboard or a visual data-preparation flow. Each calculated measure, each transformation step, each calculated column, and each relationship gets its own row and its own requirement ID, because each one is independently capable of producing a wrong number.

9.1 Data model

TableSourceGrain (what one row represents)Row count expectationKey
<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>>
RelationshipFrom tableTo tableCardinalityFilter directionRisk if wrong
<<FILL>><<FILL>><<FILL>><<FILL: one to many / many to many>><<FILL>><<FILL: drops rows / duplicates rows>>

9.2 Calculated measures

IDMeasure nameDefinition in wordsSource fieldsFilter context appliedExpected precisionIndependent check method
MEA-01<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>><<FILL: how a tester recomputes this from source>>
MEA-02<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>><<FILL>>

9.3 Query and transformation steps

IDStepWhat it doesRows inRows outWhy the row count changes
MEA-<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>><<FILL>>

9.4 Calculated columns

IDColumnTableDefinitionWhy a column rather than a measure
MEA-<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>>

9.5 Refresh and stale data

IDRequirement
MEA-<<FILL>>The dataset shall refresh on the schedule <<FILL>> from <<FILL: source>>.
MEA-<<FILL>>Every page shall display the timestamp of the last successful refresh, in <<FILL: time zone>>.
MEA-<<FILL>>On refresh failure the user shall see <<FILL: explicit stale-data banner or blocked view>>. The dashboard shall not present stale data as current.
MEA-<<FILL>>Refresh failure shall notify <<FILL: role>> within <<FILL: time>>.

9.6 Row-level security and filters

IDRequirement
MEA-<<FILL>>Role <<FILL>> shall see only <<FILL: scope>>.
MEA-<<FILL>>The sum of the records visible across all roles shall equal the total record count with no role filter applied, with no record visible to no role and none double-counted in a total.
MEA-<<FILL>>Default filter and slicer states on page load shall be <<FILL>>, and shall be visible to the user rather than implicit.

10. Limits of validity

State what the tool is not valid for. This is the section that stops a tool being reused in a context nobody assessed.

IDLimitation
LIM-01Valid only for <<FILL: product, process, study, or data type>>.
LIM-02Valid only for input ranges stated in section 2.2. Outside those ranges the tool shall reject the input rather than extrapolate.
LIM-03Not valid for <<FILL: named excluded use>>.
LIM-04The method assumes <<FILL: stated assumption>>. Where that assumption does not hold, the output is not valid and the assumption shall be checked before use.

11. Requirement-to-test traceability

Every requirement traces to at least one test case, and every test case traces back to at least one requirement. A requirement with no test is unverified. A test with no requirement is testing something nobody specified.

Requirement IDRequirement summaryTest case IDVerification method
<<FILL>><<FILL>><<FILL>>Known-answer test / boundary test / negative test / inspection / reproducibility test

Coverage statement: <<FILL: number>> requirements, <<FILL: number>> test cases, <<FILL: number>> requirements with no test case (must be zero, or each justified below).

Justified exceptions: <<FILL: none, or requirement ID and reason>>

12. Approvals

RoleNameSignatureDate
Author<<FILL>>
Independent technical reviewer<<FILL>>
Method or statistical reviewer (where applicable)<<FILL>>
Tool owner<<FILL>>
Quality Assurance<<FILL>>

Filled specimen

Specification extract for tool ANL-0007, a class A Python script that fits a stability regression for drug product potency and produces the values reported in the annual product review. Identifiers, products, and dates are illustrative.

Purpose and intended use

Produces, for one lot, the ordinary least squares slope of potency against time, the predicted potency at the proposed shelf life, and the one-sided lower 95% confidence bound on that prediction. The output populates the stability trend table in the annual product review and supports the conclusion that the lot remains within the potency specification through the proposed shelf life. Used by the stability lead, once per lot per annual review cycle. Output is the record of origin: no other system computes these values. Implements the linear regression approach described in the stability data evaluation section of <<FILL: internal SOP-ID>>, which is written against the ICH stability guidance series. This tool does not perform poolability testing across lots and does not set the shelf life; it produces the per-lot inputs to that assessment.

Input contract

ColumnTypeUnitsRequiredAllowed rangeMissingOut of range
lot_idtextnoneYesMatches <<FILL: lot format>>RejectReject
timepoint_monthsnumericmonthsYes0 to 60, non-negative, ascending, no duplicatesRejectReject
potency_pctnumeric% label claimYes50.0 to 150.0RejectReject
storage_conditiontextnoneYesOne of the controlled condition codesRejectReject
IDRequirement
IN-01Reads only the validated LIMS stability export from the read-only reporting replica. Manually edited copies are rejected by checksum comparison against the export manifest.
IN-02Rejects input if any of the four columns above is absent, naming the missing column.
IN-03Rejects input if any value in timepoint_months or potency_pct is non-numeric, naming the first offending row.
IN-04Rejects input containing fewer than six timepoints for a lot.
IN-05Records the SHA-256 hash of the input file in the provenance block.

Calculation

Ordinary least squares regression of potency on time, fitted per lot per storage condition.

Slope:

b = sum_i (t_i - t_bar) * (y_i - y_bar) / sum_i (t_i - t_bar)^2

Intercept:

a = y_bar - b * t_bar

Predicted potency at the proposed shelf life T:

y_hat(T) = a + b * T

One-sided lower 95% confidence bound on the mean response at T:

LCB(T) = y_hat(T) - t_(0.95, n-2) * s * sqrt( 1/n + (T - t_bar)^2 / Sxx )
SymbolMeaningUnits
t_itimepoint of observation imonths
y_ipotency of observation i% label claim
nnumber of timepoints for the lot and conditioncount
sresidual standard deviation, square root of the residual sum of squares divided by n minus 2% label claim
Sxxsum of squared deviations of t from its meanmonths squared
Tproposed shelf lifemonths
IDRequirement
CALC-01Computes b and a by ordinary least squares as stated above, per lot per storage condition.
CALC-02Computes y_hat(T) at the proposed shelf life supplied as a controlled parameter, not hard-coded.
CALC-03Computes LCB(T) as stated, using the one-sided t quantile at 95% with n minus 2 degrees of freedom.
CALC-04Applies no outlier exclusion. Any suspected outlier is handled by the out-of-trend procedure outside this tool, and the tool records the full input set used.
CALC-05Fails rather than extrapolating if T exceeds the last observed timepoint by more than <<FILL: months>>.

Rounding

ValuePrecisionRuleStage
slope4 decimal placeshalf-upfinal reporting only
predicted potency1 decimal placehalf-upfinal reporting only
lower confidence bound1 decimal placehalf-upfinal reporting only
IDRequirement
RND-01All intermediate computation at full double precision. Rounding applied only when writing the output.
RND-02Potency values reported to one decimal place, half-up, matching the reporting convention of the validated LIMS so that the two never disagree on a boundary value.

Reference dataset and expected values agreed before testing

Lot <<FILL: lot ID>>, long-term condition, seven timepoints.

timepoint_monthspotency_pct
0100.2
399.4
698.7
997.9
1297.2
1895.8
2494.3

Hand-computed intermediate values, verified independently by the statistician before the tool was run:

QuantityValue
n7
sum of t72
t_bar10.285714 months
sum of y683.5
y_bar97.642857 %
Sxx429.428571
Sxy-104.785714
slope b-0.2440 % per month
intercept a100.1527 %
residual standard deviation s0.040432 %
y_hat at T = 24 months94.2964, reported 94.3 %
one-sided t at 95%, 5 degrees of freedom2.0150
LCB at T = 24 months94.2343, reported 94.2 %
Lower specification limit90.0 %
ConclusionPass, lower bound above the specification limit

Error handling extract

ConditionRequired behaviourID
Non-numeric value in potency_pctNo output written, non-zero exit, message naming lot and row numberERR-03
Fewer than six timepoints for a lotNo output written for that lot, non-zero exit, message naming the lot and the count foundERR-05
Zero variance in timepoints (all timepoints identical)No output written, non-zero exit, message stating the regression is undefinedERR-06
Input file hash does not match the export manifestNo output written, non-zero exit, message stating the input was not the validated exportERR-01

Environment

python==3.11.8
numpy==1.26.4
pandas==2.2.1
scipy==1.12.0
statsmodels==0.14.1

Built into container image digest sha256:9c1d4b..., executed on analytics server ANSRV-01.

Traceability extract

Requirement IDSummaryTest case IDVerification method
IN-02Rejects missing columnTC-02Negative test
IN-03Rejects non-numeric timepoint or potencyTC-03Negative test
IN-04Rejects fewer than six timepointsTC-04Boundary and negative test
IN-05Records input hash in provenanceTC-12Inspection of output
CALC-01Slope by ordinary least squaresTC-05Known-answer test against hand calculation and an independent statistical package
CALC-02Predicted potency at shelf lifeTC-06Known-answer test
CALC-03One-sided lower 95% confidence boundTC-07Known-answer test against independent recomputation
CALC-05Fails on extrapolation beyond the allowed windowTC-08Negative test
RND-02One decimal place, half-upTC-09a, TC-09bBoundary test at 99.95 and 99.94
OUT-02Controlled result field identifiedTC-10Inspection of output schema
OUT-03Provenance block completeTC-12Inspection of output
ERR-06Undefined regression fails loudlyTC-11Negative test
ENV-02Dependencies pinnedTC-13Inspection of manifest against the running environment
SEC-01Read-only toward sourceTC-14Negative test, attempt to write to the source with the tool’s account

Coverage: 14 requirements in this extract, verified by 14 distinct test cases, with 0 requirements left without a test case. The counts match rather than the test cases outnumbering the requirements, because TC-12 verifies two requirements at once, IN-05 and OUT-03, in a single inspection of the output provenance block.

Dashboard specimen extract, for contrast

For tool ANL-0021, the class B release results dashboard, the equivalent section 9 rows read as follows for two of the fourteen measures.

IDMeasureDefinition in wordsSource fieldsFilter contextPrecisionIndependent check
MEA-03Lots released within targetCount of lots whose disposition date minus manufacture completion date is 30 days or fewer, divided by the count of lots disposed in the selected period, expressed as a percentagelot.disposition_date, lot.mfg_complete_date, lot.statusPeriod slicer, site slicer1 decimal placeRecompute from the LIMS export in a separate spreadsheet on a frozen dataset
MEA-07Out-of-specification result rateCount of results flagged out of specification divided by the count of reportable results in the selected period, expressed as a percentageresult.oos_flag, result.reportable_flagPeriod slicer, test-method slicer2 decimal placesRecompute by direct query against the source replica

Frozen verification dataset agreed before testing: 52 lots disposed in the period, of which 47 were disposed within 30 days. Expected MEA-03 = 47 / 52 = 90.4%. In the same period, 1,240 reportable results with 18 flagged out of specification. Expected MEA-07 = 18 / 1,240 = 1.45%.

Row-level security requirement for the same dashboard: the site A role sees 31 of the 52 lots and the site B role sees 21, and the two together account for all 52 with no lot visible to both.

Common inspection findings this specification prevents

  • Testing was performed but no document states what the tool was supposed to do, so no result could have failed.
  • The tool and the validated source system disagree on a value at a rounding boundary, and neither rounding rule was ever specified.
  • A filter or date-window rule quietly changes the population the calculation runs on, and nobody can say what the intended population was.
  • A specification limit, a shelf-life value, or a conversion constant is hard-coded in the tool, and it silently became wrong when the product changed.
  • The tool substitutes a default when a value is missing, and the substitution is invisible in the output.
  • A dashboard has fourteen calculated measures and one paragraph of documentation, so only the measures someone happened to think of were tested.
  • Nobody can state what the tool is not valid for, so it was reused for a second product with different assumptions.
  • Requirements exist but half of them have no corresponding test, and the gap was not visible because no traceability table was maintained.
  • A refresh failed and the dashboard kept showing last week’s data with no indication, so a reviewer looked at stale results believing they were current.

How to adapt this specification

  1. Scale the depth to the risk class. A class C tool may need only sections 1, 3.2, 4, 6, and 10, and one page is a legitimate specification for it. Class A tools get everything.
  2. Delete sections 3 to 5 for a pure dashboard and complete section 9 instead, or complete both where a dashboard sits on top of a script.
  3. Write the calculation section before writing any code. Specifications written after the code are descriptions of what the code happens to do, and they never catch the error you were trying to catch.
  4. Agree the reference dataset and the hand-computed expected values with the independent reviewer before the tool is run against them. Expected values derived from the tool’s own output are not a test.
  5. State the rounding rule of the downstream system you must agree with, by name, in RND-03. This one line prevents a recurring class of discrepancy investigation.
  6. Keep the traceability table in this document rather than in a separate matrix for small tools. A separate matrix is worth maintaining only when the requirement count runs to the dozens.
  7. Treat section 10 as the most reused part of the document. When someone asks whether the tool can also be used for a different product or a different condition, the answer is either already there or the tool needs reclassification.
  8. Confirm the current status of every cited regulation and guidance in the governing SOP before issue.
Use madhadi.com as an app Full screen, works offline, one tap from your home screen.