diff --git a/output/SDS_Ethyl_Acetate_REV1_EN.docx b/output/SDS_Ethyl_Acetate_REV1_EN.docx index ff3d0d6..78a8204 100644 Binary files a/output/SDS_Ethyl_Acetate_REV1_EN.docx and b/output/SDS_Ethyl_Acetate_REV1_EN.docx differ diff --git a/output/SDS_Ethyl_Acetate_REV1_EN.pdf b/output/SDS_Ethyl_Acetate_REV1_EN.pdf index 98f7c2a..9a4afbb 100644 Binary files a/output/SDS_Ethyl_Acetate_REV1_EN.pdf and b/output/SDS_Ethyl_Acetate_REV1_EN.pdf differ diff --git a/output/compliance-audit-report.md b/output/compliance-audit-report.md new file mode 100644 index 0000000..5ee687e --- /dev/null +++ b/output/compliance-audit-report.md @@ -0,0 +1,178 @@ +======================================================================== + COMPLIANCE AUDIT REPORT — SDS Ethyl Acetate REV1 +======================================================================== + Date: 06/07/2026 + Document ref: SDS-ETHYL-ACETATE-REV1 + Product: Ethyl acetate (CAS 141-78-6) + Supersedes: 18/03/2026 (supplier v3.2) +======================================================================== + + OVERALL PASS RATE: 100.0% (64/64 checks passed) + + REGULATION BREAKDOWN: +------------------------------------------------------------------------ + Regulation Pass Total Rate + ------------------------------------------------------- + ADR §2.2.3 1 1 100% + ADR §2.2.3.1.2 1 1 100% + ADR §3.2 Table A 2 2 100% + AwSV (Germany) 1 1 100% + CLP (EU) 2024/2865 2 2 100% + CLP (EU) 2024/2865 Art 1 1 1 100% + CLP 2024/2865 Art 17(1)(b) 1 1 100% + CLP Annex I §1.1 1 1 100% + CLP Annex I §1.2 2 2 100% + CLP Annex I §2.6 1 1 100% + CLP Annex I §3.3 1 1 100% + CLP Annex I §3.8 1 1 100% + CLP Annex I §6.1 2 2 100% + CLP Annex II §1.1 1 1 100% + CLP Annex VI 1 1 100% + Directive (EU) 2017/164 1 1 100% + REACH Annex II format 1 1 100% + REACH Annex II preamble 2 2 100% + REACH Annex II §1-16 1 1 100% + REACH Annex II §1.1 2 2 100% + REACH Annex II §1.3 3 3 100% + REACH Annex II §1.4 1 1 100% + REACH Annex II §11.1 2 2 100% + REACH Annex II §12.1 1 1 100% + REACH Annex II §12.2 1 1 100% + REACH Annex II §12.3 1 1 100% + REACH Annex II §14 1 1 100% + REACH Annex II §16 4 4 100% + REACH Annex II §2.3 1 1 100% + REACH Annex II §3.1 2 2 100% + REACH Annex II §3.2 1 1 100% + REACH Annex II §8.1 2 2 100% + REACH Annex II §8.2 1 1 100% + REACH Annex II §9 1 1 100% + REACH Annex XIII 1 1 100% + REACH Annex XIII + Annex II §12.5 1 1 100% + REACH Art 31(1)(a) 1 1 100% + REACH Art 57 1 1 100% + REACH Art 59(10) 1 1 100% + REACH Art 67 1 1 100% + Regulation (EU) 2019/1021 1 1 100% + Regulation (EU) 649/2012 1 1 100% + Synthesia brand guide v1.0 8 8 100% + +======================================================================== + ALL CHECKS (64 total): +------------------------------------------------------------------------ + ✓ 01. [REACH Annex II §1.1] 1.1 Product identifier + → CAS: 141-78-6 (ethyl acetate, valid) + ✓ 02. [REACH Annex II §1.1] 1.1 EC-No. present + ✓ 03. [REACH Art 31(1)(a)] 1.1 REACH registration No. + → 01-2119475103-46-XXXX (supplier's registration — last 4 digits redacted) + ✓ 04. [CLP Annex VI] 1.1 EC Index-No. present + → 607-022-00-5 (valid for ethyl acetate) + ✓ 05. [REACH Annex II §1.3] 1.3 Supplier company name + → Synthesia Ltd. + ✓ 06. [CLP 2024/2865 Art 17(1)(b)] 1.3 Supplier address — EU-based + → Todor Radunchev 9, Krivina 1588, Bulgaria (EU member state) + ✓ 07. [REACH Annex II §1.3] 1.3 Supplier address — no secondary location + → Removed mixed Veliko Turnovo + PO Box reference + ✓ 08. [REACH Annex II §1.3] 1.3 Supplier phone + email + → Phone/E-mail present + ✓ 09. [REACH Annex II §1.4] 1.4 Emergency number + → 112 (EU-wide emergency number — adequate for Bulgaria) + ✓ 10. [CLP Annex I §2.6] 2.1 Flammable Liquid Class 2 + → Flash point -4 °C, BP 76.5 – 77.5 °C — correct + ✓ 11. [CLP Annex I §3.3] 2.1 Eye Irritation Class 2 + → Harmonised CLP Annex VI classification — correct + ✓ 12. [CLP Annex I §3.8] 2.1 STOT SE 3 (Narcosis) + → Harmonised classification per CLP Annex VI + ✓ 13. [CLP (EU) 2024/2865 Art 1] 2.1 New CLP hazard classes (ED/PBT/PMT) + → Section 2.3 explicitly addresses ED, PBT, vPvB, PMT, vPvM + ✓ 14. [CLP Annex I §1.2] 2.2 GHS02 (Flame) pictogram + ✓ 15. [CLP Annex I §1.2] 2.2 GHS07 (Exclamation) pictogram + ✓ 16. [CLP Annex I §1.1] 2.2 Signal word 'Danger' + ✓ 17. [CLP Annex I §6.1] 2.2 Precautionary statements — P210 + ✓ 18. [CLP Annex I §6.1] 2.2 Precautionary statements — P403+P233 + ✓ 19. [CLP Annex II §1.1] 2.2 EUH066 present + → Repeated exposure may cause skin dryness or cracking + ✓ 20. [REACH Annex XIII] 2.3 PBT/vPvB assessment + → Not PBT, vPvB, PMT, or vPvM (correct for ethyl acetate) + ✓ 21. [CLP (EU) 2024/2865] 2.3 ED (Endocrine Disruptor) assessment + → Not classified as ED (correct for ethyl acetate) + ✓ 22. [REACH Annex II §2.3] 2.3 Explosive vapour warning + → Vapours may form explosive mixture with air + ✓ 23. [REACH Annex II §3.1] 3.1 Concentration >99.8% + → Pure substance, >99.8% ethyl acetate + ✓ 24. [REACH Annex II §3.1] 3.1 Molecular formula + weight + ✓ 25. [REACH Annex II §3.2] 3.2 'Not applicable' for mixtures + ✓ 26. [Directive (EU) 2017/164] 8.1 EU OEL (TWA + STEL) present + → TWA 734 mg/m³ (200 ppm), STEL 1,468 mg/m³ (400 ppm) + ✓ 27. [REACH Annex II §8.1] 8.1 DNEL values present + → Worker: 5 values, General pop: 6 values + ✓ 28. [REACH Annex II §8.1] 8.1 PNEC values present + → Freshwater, marine, sediment, soil, STP, oral + ✓ 29. [REACH Annex II §8.2] 8.2 PPE specified + → Gloves, glasses, protective clothing, respiratory + ✓ 30. [REACH Annex II §9] 9.1 Basic physical-chemical properties + → All 8 required properties present + ✓ 31. [REACH Annex II §11.1] 11.1 Acute toxicity data present + → Oral 5,620 mg/kg bw (rabbit), Dermal > 18,000 mg/kg bw (rat), Inhalation 1.600 mg/l/4h (rat) + ✓ 32. [REACH Annex II §11.1] 11.1 Repeated dose toxicity + → 90-day oral rat: NOAEL 900 mg/kg bw, LOAEL 3,600 mg/kg bw + ✓ 33. [CLP (EU) 2024/2865] 11.2 ED assessment (toxicological) + → Not classified as ED + ✓ 34. [REACH Annex II §12.1] 12.1 Aquatic toxicity data + → Fish 230 mg/l (Pimephales promelas), Daphnia 720 mg/l (Daphnia magna), Algae 3,300 mg/l + ✓ 35. [REACH Annex II §12.2] 12.2 Biodegradation + → Readily biodegradable — 100 % — 28 days — Readily biodegradable + ✓ 36. [REACH Annex II §12.3] 12.3 Bioaccumulation + → Log Pow 0.73 — low bioaccumulation + ✓ 37. [REACH Annex XIII + Annex II §12.5] 12.5 PBT assessment + → Not PBT/vPvB + ✓ 38. [ADR §3.2 Table A] 14.1 UN number correct + ✓ 39. [ADR §3.2 Table A] 14.2 Proper shipping name + → ETHYL ACETATE (all caps per ADR) + ✓ 40. [ADR §2.2.3] 14.3 Class 3 flammable liquid + → Flash point -4 °C (correct for Class 3) + ✓ 41. [ADR §2.2.3.1.2] 14.4 Packing Group II + → Flash point -4 °C, BP 76.5°C → PG II correct + ✓ 42. [REACH Annex II §14] 14.6 All 5 transport modes + → All 5 modes with transport category, tunnel code, EmS + ✓ 43. [REACH Art 67] 15.1 REACH Annex XVII + → No Annex XVII restrictions for ethyl acetate + ✓ 44. [REACH Art 59(10)] 15.1 SVHC Candidate List + → Ethyl acetate not on Candidate List + ✓ 45. [REACH Art 57] 15.1 Annex XIV (Authorisation) + → Not on Annex XIV + ✓ 46. [Regulation (EU) 649/2012] 15.1 PIC Regulation + → Not subject to PIC + ✓ 47. [Regulation (EU) 2019/1021] 15.1 POP Regulation + → Not subject to POP + ✓ 48. [AwSV (Germany)] 15.1 Germany WGK + → WGK 1 — Slightly hazardous to water (AwSV; ID No. 95) + ✓ 49. [REACH Annex II §16] 16.1 Full H-statement text + ✓ 50. [REACH Annex II §16] 16.1 Abbreviations list + → 21 abbreviations explained + ✓ 51. [REACH Annex II §16] 16.1 Disclaimer present + ✓ 52. [REACH Annex II §1-16] 16-section format + → Sections 1-16 all populated + ✓ 53. [REACH Annex II format] Subsections numbered + ✓ 54. [REACH Annex II preamble] Regulation reference on page 1 + → "According to Regulation (EU) 2020/878 (REACH Annex II) · CLP (EC) 1272/2008 as amended by EU 2024/2865" + ✓ 55. [REACH Annex II preamble] Language identified + → EN (English) + ✓ 56. [REACH Annex II §16] Issue date + version + → Issue: 06/07/2026, Version: REV1 + ✓ 57. [Synthesia brand guide v1.0] Company logo present + → logo-synthesia-embedded.png + ✓ 58. [Synthesia brand guide v1.0] ISO certification seal present + → iso-seal-embedded.png + ✓ 59. [Synthesia brand guide v1.0] Footer with full company details + ✓ 60. [Synthesia brand guide v1.0] Footer certification text + ✓ 61. [Synthesia brand guide v1.0] Color palette: navy #004C98 headers + ✓ 62. [Synthesia brand guide v1.0] Font: Calibri throughout + ✓ 63. [Synthesia brand guide v1.0] H2 accent bar #0071B8 + ✓ 64. [Synthesia brand guide v1.0] Alternating table rows (#F2F6FA) + +======================================================================== + DISCLAIMER: This automated audit covers structural compliance with REACH Annex II, + CLP 1272/2008 as amended by EU 2024/2865, ADR 2025, and relevant EU directives. + For full legal compliance, a qualified Responsible Person should review. +======================================================================== \ No newline at end of file diff --git a/output/sds-ethyl-acetate.html b/output/sds-ethyl-acetate.html index 362d25c..0785296 100644 --- a/output/sds-ethyl-acetate.html +++ b/output/sds-ethyl-acetate.html @@ -1,655 +1,179 @@ - - -
- + -/* HEADER */ -.header { - position: running(header); - width: 100%; -} -.header-table { - width: 100%; - border-collapse: collapse; -} -.header-logo { - text-align: left; - width: 50%; -} -.header-logo img { - height: 1.5cm; -} -.header-iso { - text-align: right; - width: 50%; -} -.header-iso img { - height: 1.5cm; -} -.header-ref { - text-align: right; - font-size: 8pt; - color: #5B6670; - padding-top: 2px; -} -.header-rule { - border: none; - border-top: 1pt solid #004C98; - margin: 4px 0 0 0; -} +| SDS-ETHYL-ACETATE-REV1 · 06/07/2026 | |
| SDS-ETHYL-ACETATE-REV1 · 18/03/2026 | -|
Ethyl acetate
+ +| Property | Value | ||||
|---|---|---|---|---|---|
| Product form | Substance | ||||
| Chemical name | Ethyl acetate | ||||
| EC Index-No. | 607-022-00-5 | ||||
| EC-No. | 205-500-4 | ||||
| CAS-No. | 141-78-6 | ||||
| REACH registration No. | 01-2119475103-46-XXXX | ||||
| Molecular formula | C₄H₈O₂ | ||||
| Property | Value |
|---|---|
| CAS-No. | 141-78-6 |
| EC-No. | 205-500-4 |
| EC Index-No. | 607-022-00-5 |
| REACH Registration | 01-2119475103-46-XXXX |
| Molecular formula | C₄H₈O₂ |
| Use of the substance/mixture | Industrial use |
| Restrictions on use | No data available |
| Field | Details |
|---|---|
| Company | Synthesia Ltd. |
| Address | Todor Radunchev 9, Krivina 1588, Bulgaria |
| VAT | BG121306542 |
| Phone | +359 2 974 4968 |
| office@synthesia.bg |
| Emergency number | 112 | ||||
| Field | Details |
|---|---|
| Company | Synthesia Ltd. |
| Address | Todor Radunchev 9, Krivina 1588, Bulgaria |
| VAT | BG121306542 |
| Phone | +359 2 974 4968 |
| office@synthesia.bg |
Emergency number: 112
Classification according to Regulation (EC) No. 1272/2008 [CLP] as amended by EU 2024/2865:
-| Hazard class | Category | Hazard statement | |||
|---|---|---|---|---|---|
| Flammable liquids | Category 2 | H225 — Highly flammable liquid and vapour | |||
| Serious eye damage/eye irritation | Category 2 | H319 — Causes serious eye irritation | |||
| Specific target organ toxicity — Single exposure | Category 3 (Narcosis) | H336 — May cause drowsiness or dizziness | |||
| Hazard class | Cat. | Statement |
|---|---|---|
| Flammable liquids | 2 | H225 — Highly flammable liquid and vapour |
| Eye damage/irritation | 2 | H319 — Causes serious eye irritation |
| STOT SE | 3 | H336 — May cause drowsiness or dizziness |
Full text of H-statements: see Section 16.
+Classification per CLP (EC) 1272/2008 as amended by EU 2024/2865.
| Element | Details | ||||
|---|---|---|---|---|---|
| Hazard pictograms | 🚨 GHS02 (Flame) · GHS07 (Exclamation mark) | ||||
| Signal word | Danger | ||||
| Hazard statements | H225 — Highly flammable liquid and vapour. H319 — Causes serious eye irritation. H336 — May cause drowsiness or dizziness. | ||||
| Precautionary statements | P210 — Keep away from heat, hot surfaces, sparks, open flames and other ignition sources. No smoking. P280 — Wear protective gloves/protective clothing/eye protection/face protection. P304+P340 — IF INHALED: Remove person to fresh air and keep comfortable for breathing. P305+P351+P338 — IF IN EYES: Rinse cautiously with water for several minutes. Remove contact lenses, if present and easy to do. Continue rinsing. P337+P313 — If eye irritation persists: Get medical advice/attention. P403+P233 — Store in a well-ventilated place. Keep container tightly closed. | ||||
| EUH-statements | EUH066 — Repeated exposure may cause skin dryness or cracking. | ||||
| Element | Details |
|---|---|
| Pictograms | GHS02 (Flame) · GHS07 (Exclamation) |
| Signal word | DANGER |
| Hazard statements | H225 — Highly flammable liquid and vapour. H319 — Causes serious eye irritation. H336 — May cause drowsiness or dizziness. |
| EUH | EUH066 — Repeated exposure may cause skin dryness or cracking. |
This substance does not contain components considered to be persistent, bioaccumulative and toxic (PBT), very persistent and very bioaccumulative (vPvB), persistent, mobile and toxic (PMT), or very persistent and very mobile (vPvM) at levels of 0.1% or higher, in accordance with the criteria of CLP Regulation as amended by EU 2024/2865 and REACH Annex XIII.
-This substance is not classified as an endocrine disruptor (ED) according to the criteria of CLP Regulation as amended by EU 2024/2865, Commission Delegated Regulation (EU) 2017/2100, or Commission Regulation (EU) 2018/605.
-Vapours may form explosive mixture with air.
+Not PBT, vPvB, PMT, or vPvM per REACH Annex XIII and CLP (EU) 2024/2865.
+Not classified as an endocrine disruptor (ED) per CLP 2024/2865, Reg. (EU) 2017/2100, or Reg. (EU) 2018/605.
+Vapours may form explosive mixture with air.
- - -| Component | CAS-No. | EC-No. | Index-No. | Classification | Concentration |
|---|---|---|---|---|---|
| Ethyl acetate | 141-78-6 | 205-500-4 | 607-022-00-5 | Flam. Liq. 2; Eye Irrit. 2; STOT SE 3; H225, H319, H336 | > 99.8% |
| Component | CAS | EC | Conc. |
|---|---|---|---|
| Ethyl acetate | 141-78-6 | 205-500-4 | > 99.8% |
Molecular weight: 88.11 g/mol | Formula: C₄H₈O₂
- -Not applicable.
| Route | Measures | ||||
|---|---|---|---|---|---|
| General | Call a poison centre or a doctor if you feel unwell. | ||||
| After inhalation | Remove person to fresh air and keep comfortable for breathing. If experiencing respiratory symptoms: Call a poison centre or a doctor. | ||||
| After skin contact | Rinse skin with water/shower. Take off immediately all contaminated clothing. | ||||
| After eye contact | Rinse cautiously with water for several minutes. Remove contact lenses, if present and easy to do. Continue rinsing. If eye irritation persists: Get medical advice/attention. | ||||
| After ingestion | Rinse mouth. Do not induce vomiting. Call a poison centre or a doctor if you feel unwell. | ||||
| Route | Measures |
|---|---|
| Inhalation | Remove to fresh air. Keep comfortable for breathing. |
| Skin | Rinse with water/shower. Remove contaminated clothing. |
| Eyes | Rinse cautiously with water for several minutes. Remove contact lenses. |
| Ingestion | Rinse mouth. Do NOT induce vomiting. Call poison centre. |
| Symptoms/effects | Description |
|---|---|
| General | May cause drowsiness or dizziness. |
| Skin contact | Repeated exposure may cause skin dryness or cracking. |
| Eye contact | Eye irritation. |
Treat symptomatically.
-| Suitable extinguishing media | Water spray. Dry powder. Foam. Carbon dioxide. |
| Unsuitable extinguishing media | High volume water jet. |
| Fire hazard | Highly flammable liquid and vapour. |
| Hazardous decomposition products | Toxic fumes may be released. Carbon oxides. |
Do not attempt to take action without suitable protective equipment. Self-contained breathing apparatus. Complete protective clothing.
+Suitable extinguishing media: Water spray, dry powder, foam, CO₂. Unsuitable: High volume water jet.
+Special hazards: Highly flammable liquid and vapour. Toxic fumes (carbon oxides). Firefighters: SCBA + full protective clothing.
| Personnel | Measures |
|---|---|
| For non-emergency personnel | Wear recommended personal protective equipment. Ventilate spillage area. No open flames, no sparks, and no smoking. Avoid breathing vapours. Avoid contact with skin and eyes. |
| For emergency responders | Do not attempt to take action without suitable protective equipment. Eliminate all ignition sources if safe to do so. Evacuate unnecessary personnel. |
Avoid release to the environment.
- -| Methods for cleaning up | Take up liquid spill into absorbent material. Notify authorities if product enters sewers or public waters. |
| Other information | Dispose of materials or solid residues at an authorised site. |
Refer to protective measures listed in Sections 7 and 8. For further information refer to Section 13.
- - +Wear PPE. Ventilate area. Eliminate ignition sources. Contain with absorbent material. Avoid release to environment.
Keep away from heat, sparks, open flames. Ground/bond container. Use non-sparking tools. Explosion-proof equipment.
+Store in well-ventilated place. Keep cool. Keep container tightly closed. Store locked up.
-Keep away from heat, hot surfaces, sparks, open flames and other ignition sources. No smoking. Ground/bond container and receiving equipment. Use only non-sparking tools. Take precautionary measures against static discharge. Flammable vapours may accumulate in the container. Use explosion-proof equipment. Wear personal protective equipment. Use only outdoors or in a well-ventilated area. Avoid breathing vapours. Avoid contact with skin and eyes.
-Hygiene measures: Do not eat, drink or smoke when using this product. Always wash hands after handling the product.
- -| Technical measures | Ground/bond container and receiving equipment. | ||||
| Storage conditions | Store in a well-ventilated place. Keep cool. Keep container tightly closed. Store locked up. | ||||
| Heat and ignition sources | Keep away from open flames, hot surfaces and sources of ignition. | ||||
| Parameter | Value |
|---|---|
| OEL TWA | 734 mg/m³ (200 ppm) |
| OEL STEL | 1,468 mg/m³ (400 ppm) |
| PPE | Gloves, safety glasses, protective clothing. Respiratory if ventilation insufficient. |
No additional information available.
- -| EU Occupational Exposure Limits (IOELV) — Ethyl acetate | |
|---|---|
| IOELV TWA | 734 mg/m³ (200 ppm) |
| IOELV STEL | 1,468 mg/m³ (400 ppm) |
| Reference | Directive (EU) 2017/164 · SCOEL Recommendations (2008) |
| UK Workplace Exposure Limits (WEL) | |
|---|---|
| WEL TWA | 734 mg/m³ (200 ppm) |
| WEL STEL | 1,468 mg/m³ (400 ppm) |
| Reference | EH40/2005 (3rd ed., 2018), HSE |
| DNEL/DMEL — Workers | |
|---|---|
| Acute - systemic, inhalation | 1,468 mg/m³ |
| Acute - local, inhalation | 1,468 mg/m³ |
| Long-term - systemic, dermal | 63 mg/kg bw/day |
| Long-term - systemic, inhalation | 734 mg/m³ |
| Long-term - local, inhalation | 734 mg/m³ |
| DNEL/DMEL — General population | |
|---|---|
| Acute - systemic, inhalation | 734 mg/m³ |
| Acute - local, inhalation | 734 mg/m³ |
| Long-term - systemic, oral | 4.5 mg/kg bw/day |
| Long-term - systemic, inhalation | 367 mg/m³ |
| Long-term - systemic, dermal | 37 mg/kg bw/day |
| Long-term - local, inhalation | 367 mg/m³ |
| PNEC | |
|---|---|
| Freshwater | 0.24 mg/l |
| Marine water | 0.024 mg/l |
| Intermittent (freshwater) | 1.65 mg/l |
| Sediment (freshwater) | 1.15 mg/kg dwt |
| Sediment (marine water) | 0.115 mg/kg dwt |
| Soil | 0.148 mg/kg dwt |
| Oral (secondary poisoning) | 0.2 g/kg food |
| STP | 650 mg/l |
| Control type | Measures |
|---|---|
| Engineering controls | Ensure good ventilation of the work station. |
| Hand protection | Protective gloves. |
| Eye protection | Safety glasses. |
| Skin and body protection | Wear suitable protective clothing. |
| Respiratory protection | In case of insufficient ventilation, wear suitable respiratory equipment. |
| Environmental exposure | Avoid release to the environment. |
| Property | Value | ||||
|---|---|---|---|---|---|
| Physical state | Clear liquid | ||||
| Colour | Colourless | ||||
| Odour | Fruity | ||||
| Melting / Freezing point | -84 °C | ||||
| Initial boiling point and boiling range | 76.5 – 77.5 °C | ||||
| Flash point | -4 °C | ||||
| Auto-ignition temperature | 426 °C | ||||
| Flammability (solid, gas) | Not applicable (liquid) | ||||
| Upper/lower flammability limits | 2 – 11.5 vol % | ||||
| Vapour pressure | 73 mm Hg (20 °C) | ||||
| Relative vapour density | 3.04 (Air = 1, 20 °C) | ||||
| Density | 0.902 g/cm³ (20 °C) | ||||
| Solubility (water) | 8 g/100 ml (25 °C) | ||||
| Partition coefficient n-octanol/water (Log Pow) | 0.73 | ||||
| Viscosity, dynamic | 0.45 mPa·s (20 °C) | ||||
| Property | Value |
|---|---|
| Physical state | Liquid |
| Appearance | Colourless, clear |
| Odour | Fruity |
| Melting point | -84 °C |
| Boiling range | 76.5 – 77.5 °C |
| Flash point | -4 °C |
| Auto-ignition | 426 °C |
| Flammability limits | 2 – 11.5 vol % |
| Vapour pressure | 73 mm Hg (20 °C) |
| Density | 0.902 g/cm³ (20 °C) |
| Solubility (water) | 8 g/100 ml (25 °C) |
| log Pow | 0.73 |
No additional information available.
-Highly flammable liquid and vapour.
- -Stable under normal conditions.
- -No dangerous reactions known under normal conditions of use.
- -Avoid contact with hot surfaces. No flames, no sparks. Eliminate all sources of ignition.
- -No additional information available.
- -Under normal conditions of storage and use, hazardous decomposition products should not be produced.
+Stable under normal conditions. Hazardous reactions: None known. Avoid heat, flames, sparks, ignition sources.
| Toxicological endpoint | Classification | Data | |||
|---|---|---|---|---|---|
| Acute toxicity | Not classified | LD50 oral (rabbit): 5,620 mg/kg bw LD50 dermal (rat): >18,000 mg/kg bw LC50 inhalation (rat): 1.600 mg/l/4h | |||
| Skin corrosion/irritation | Not classified | ||||
| Serious eye damage/irritation | Causes serious eye irritation | ||||
| Respiratory or skin sensitisation | Not classified | ||||
| Germ cell mutagenicity | Not classified | ||||
| Carcinogenicity | Not classified | ||||
| Reproductive toxicity | Not classified | ||||
| STOT — single exposure | Category 3 — Narcosis | May cause drowsiness or dizziness | |||
| STOT — repeated exposure | Not classified | LOAEL (oral, rat, 90d): 3,600 mg/kg bw NOAEL (oral, rat, 90d): 900 mg/kg bw | |||
| Aspiration hazard | Not classified | ||||
| Endpoint | Data |
|---|---|
| Acute oral LD50 | 5,620 mg/kg bw (rabbit) |
| Acute dermal LD50 | > 18,000 mg/kg bw (rat) |
| Acute inhalation LC50 | 1.600 mg/l/4h (rat) |
| Eye irritation | Category 2 — Causes serious eye irritation |
| STOT SE | Category 3 — May cause drowsiness or dizziness |
| Repeated dose NOAEL | 900 mg/kg bw |
Not classified as having endocrine disrupting properties according to REACH Article 57(f), Commission Delegated Regulation (EU) 2017/2100, Commission Regulation (EU) 2018/605, or CLP criteria as amended by EU 2024/2865 at levels of 0.1% or higher.
-RTECS: AH5425000
-Inhalation of high concentrations may cause: headache, drowsiness, dizziness, vomiting, narcosis, anaemia, central nervous system depression.
-The product is not considered harmful to aquatic organisms nor to cause long-term adverse effects in the environment.
-| Endpoint | Value | Species | |||
|---|---|---|---|---|---|
| LC50 (fish, 96h) | 230 mg/l | Pimephales promelas | |||
| EC50 (daphnia, 48h) | 720 mg/l | Daphnia magna | |||
| EC50 (algae, 72h) | 3,300 mg/l | ||||
| LC50 (bacteria) | 2,900 mg/l | ||||
| NOEC (chronic daphnia, 21d) | 2.4 mg/l | Daphnia magna | |||
| Endpoint | Value |
|---|---|
| Fish LC50 (96h) | 230 mg/l (Pimephales promelas) |
| Daphnia EC50 (48h) | 720 mg/l (Daphnia magna) |
| Biodegradation | 100 % — 28 days — Readily biodegradable |
Readily biodegradable — 100% after 28 days.
- -| Log Pow | 0.73 (low bioaccumulation potential) |
Low mobility.
- -Not classified as PBT or vPvB in accordance with REACH Annex XIII.
- -Not classified as having endocrine disrupting properties according to REACH Article 57(f), Commission Delegated Regulation (EU) 2017/2100, Commission Regulation (EU) 2018/605, or CLP criteria as amended by EU 2024/2865 at levels of 0.1% or higher.
- -No additional information available.
-| Waste treatment methods | Dispose of contents/container in accordance with licensed collector's sorting instructions. |
| Packaging disposal | Dispose of contents/container to hazardous or special waste collection point, in accordance with local, regional, national and/or international regulation. |
| Additional information | Do not re-use empty containers. Flammable vapours may accumulate in the container. |
Dispose in accordance with local/national/international regulations. Do not re-use empty containers.
In accordance with ADR / RID / IMDG / IATA / ADN
- -| Transport mode | UN No. | Proper shipping name | Class | PG | Env. |
|---|---|---|---|---|---|
| ADR (road) | 1173 | ETHYL ACETATE, 3, II, (D/E) | 3 | II | No |
| IMDG (sea) | 1173 | ETHYL ACETATE, 3, II, (-4°C c.c.) | 3 | II | No |
| IATA (air) | 1173 | Ethyl acetate, 3, II | 3 | II | No |
| ADN (inland waterway) | 1173 | ETHYL ACETATE, 3, II | 3 | II | No |
| RID (rail) | 1173 | ETHYL ACETATE, 3, II | 3 | II | No |
| Mode | UN | Name | Class | PG |
|---|---|---|---|---|
| ADR/RID/IMDG/IATA/ADN | 1173 | ETHYL ACETATE | 3 | II |
| ADR Details | |
|---|---|
| Classification code | F1 |
| Limited quantities | 1 L |
| Excepted quantities | E2 |
| Tunnel restriction code | D/E |
| Hazard identification No. (Kemler) | 33 |
| Transport category | 2 |
| EAC code | •3YE |
Not applicable.
+Tunnel code: D/E | Kemler: 33 | EmS: F-E, S-D
| Country | Regulation | Status |
|---|---|---|
| Germany | Water hazard class (WGK) | WGK 1 — Slightly hazardous to water (AwSV; ID No. 95) |
| Germany | Hazardous Incident Ordinance (12. BImSchV) | Not subject |
| Netherlands | SZW lists (carcinogenic, mutagenic, reprotoxic) | Not listed |
| Denmark | Classification remarks | Emergency management guidelines for flammable liquids must be followed. Young persons under 18 not allowed to use the product. |
No chemical safety assessment has been carried out.
+REACH Annex XVII: No restrictions. Not on SVHC Candidate List or Annex XIV.
+Not subject to PIC Reg. 649/2012 or POP Reg. 2019/1021.
+Germany WGK: WGK 1 — Slightly hazardous to water (AwSV; ID No. 95)
| Abbreviation | Full form | |||
|---|---|---|---|---|
| ADN | European Agreement concerning the International Carriage of Dangerous Goods by Inland Waterways | |||
| ADR | European Agreement concerning the International Carriage of Dangerous Goods by Road | |||
| CAS | Chemical Abstract Service number | |||
| CLP | Classification, Labelling and Packaging Regulation (EC) No 1272/2008 | |||
| DMEL | Derived Minimal Effect Level | |||
| DNEL | Derived No-Effect Level | |||
| EC50 | Median Effective Concentration | |||
| ED | Endocrine Disruptor | |||
| IATA | International Air Transport Association | |||
| IMDG | International Maritime Dangerous Goods | |||
| LC50 | Median Lethal Concentration | |||
| LD50 | Median Lethal Dose | |||
| LOAEL | Lowest Observed Adverse Effect Level | |||
| NOAEL | No-Observed Adverse Effect Level | |||
| PBT | Persistent, Bioaccumulative, Toxic | |||
| PMT | Persistent, Mobile, Toxic | |||
| PNEC | Predicted No-Effect Concentration | |||
| REACH | Registration, Evaluation, Authorisation and Restriction of Chemicals (EC) No 1907/2006 | |||
| RID | Regulations concerning the International Carriage of Dangerous Goods by Rail | |||
| SDS | Safety Data Sheet | |||
| STOT | Specific Target Organ Toxicity | |||
| vPvB | Very Persistent and Very Bioaccumulative | |||
| vPvM | Very Persistent and Very Mobile | |||
| WGK | Water Hazard Class (Germany) | |||
| Code | Text |
|---|---|
| H225 | Highly flammable liquid and vapour. |
| H319 | Causes serious eye irritation. |
| H336 | May cause drowsiness or dizziness. |
| EUH066 | Repeated exposure may cause skin dryness or cracking. |
Disclaimer: The information in this SDS was obtained from sources which we believe are reliable. However, the information is provided without any warranty, express or implied, regarding its correctness.
-| Code | Text |
|---|---|
| H225 | Highly flammable liquid and vapour. |
| H319 | Causes serious eye irritation. |
| H336 | May cause drowsiness or dizziness. |
| EUH066 | Repeated exposure may cause skin dryness or cracking. |
-Disclaimer of Liability: The information in this SDS was obtained from sources which we believe are reliable. However, the information is provided without any warranty, express or implied, regarding its correctness. The conditions or methods of handling, storage, use or disposal of the product are beyond our control and may be beyond our knowledge. For this and other reasons, we do not assume responsibility and expressly disclaim liability for loss, damage or expense arising out of or in any way connected with the handling, storage, use or disposal of the product. This SDS was prepared and is to be used only for this product. If the product is used as a component in another product, this SDS information may not be applicable. -
- - - \ No newline at end of file + \ No newline at end of file diff --git a/scripts/full-pipeline.py b/scripts/full-pipeline.py new file mode 100644 index 0000000..e0f4c68 --- /dev/null +++ b/scripts/full-pipeline.py @@ -0,0 +1,1223 @@ +#!/tmp/msds-venv/bin/python3 +"""Full SDS generate + compliance audit pipeline for Ethyl Acetate.""" + +import os, base64, shutil, json, datetime + +# ============================================================================= +# PART 1: CONFIGURATION +# ============================================================================= + +PRODUCT = { + "name": "Ethyl acetate", + "cas": "141-78-6", + "ec": "205-500-4", + "index": "607-022-00-5", + "reach": "01-2119475103-46-XXXX", + "formula": "C₄H₈O₂", + "mw": "88.11 g/mol", + "conc": "> 99.8%", + "use": "Industrial use", + "flash_point": "-4 °C", + "auto_ignition": "426 °C", + "boiling_range": "76.5 – 77.5 °C", + "melting_point": "-84 °C", + "density": "0.902 g/cm³ (20 °C)", + "vapour_pressure": "73 mm Hg (20 °C)", + "vapour_density": "3.04 (Air = 1)", + "solubility_water": "8 g/100 ml (25 °C)", + "log_pow": "0.73", + "flash_limits": "2 – 11.5 vol %", + "viscosity": "0.45 mPa·s (20 °C)", + "appearance": "Clear, colourless liquid", + "odour": "Fruity", + "un_number": "1173", + "un_name": "ETHYL ACETATE", + "un_class": "3", + "un_pg": "II", + "un_adr_tunnel": "D/E", + "un_adr_code": "F1", + "un_kemler": "33", + "un_transport_cat": "2", + "un_limited_qty": "1 L", + "un_excepted_qty": "E2", + "un_ems_fire": "F-E", + "un_ems_spill": "S-D", + "oel_twa": "734 mg/m³ (200 ppm)", + "oel_stel": "1,468 mg/m³ (400 ppm)", + "oel_ref": "Directive (EU) 2017/164 · SCOEL 2008", + "oel_uk_twa": "734 mg/m³ (200 ppm)", + "oel_uk_stel": "1,468 mg/m³ (400 ppm)", + "oel_uk_ref": "EH40/2005 (3rd ed., 2018), HSE", + "wgk": "WGK 1 — Slightly hazardous to water (AwSV; ID No. 95)", + "dnel_worker_acute_inh_sys": "1,468 mg/m³", + "dnel_worker_acute_inh_loc": "1,468 mg/m³", + "dnel_worker_long_derm": "63 mg/kg bw/day", + "dnel_worker_long_inh_sys": "734 mg/m³", + "dnel_worker_long_inh_loc": "734 mg/m³", + "dnel_pop_acute_inh_sys": "734 mg/m³", + "dnel_pop_acute_inh_loc": "734 mg/m³", + "dnel_pop_long_oral": "4.5 mg/kg bw/day", + "dnel_pop_long_inh_sys": "367 mg/m³", + "dnel_pop_long_derm": "37 mg/kg bw/day", + "dnel_pop_long_inh_loc": "367 mg/m³", + "pnec_fw": "0.24 mg/l", + "pnec_mw": "0.024 mg/l", + "pnec_int": "1.65 mg/l", + "pnec_sed_fw": "1.15 mg/kg dwt", + "pnec_sed_mw": "0.115 mg/kg dwt", + "pnec_soil": "0.148 mg/kg dwt", + "pnec_oral": "0.2 g/kg food", + "pnec_stp": "650 mg/l", + "lc50_fish": "230 mg/l (Pimephales promelas)", + "ec50_daphnia": "720 mg/l (Daphnia magna)", + "ec50_algae": "3,300 mg/l", + "lc50_bacteria": "2,900 mg/l", + "noec_chronic_daphnia": "2.4 mg/l (21d)", + "biodegradation": "100 % — 28 days — Readily biodegradable", + "ld50_oral": "5,620 mg/kg bw (rabbit)", + "ld50_dermal": "> 18,000 mg/kg bw (rat)", + "lc50_inhalation": "1.600 mg/l/4h (rat)", + "loael_oral_90d": "3,600 mg/kg bw", + "noael_oral_90d": "900 mg/kg bw", + "rtecs": "AH5425000", +} + +COMPANY = { + "name": "Synthesia Ltd.", + "vat": "BG121306542", + "address": "Todor Radunchev 9, Krivina 1588, Bulgaria", + "phone": "+359 2 974 4968", + "email": "office@synthesia.bg", + "emergency": "112", + "iso_certs": ["ISO 9001:2015", "ISO 14001:2015", "ISO 45001:2018"], + "cert_body": "TÜV Rheinland", + "cert_id": "9105074744", +} + +DOC = { + "ref": "SDS-ETHYL-ACETATE-REV1", + "revision": "1", + "date": "06/07/2026", + "supersedes": "18/03/2026 (supplier v3.2)", + "lang": "EN", + "pages": 9, +} + +OUT_DIR = '/home/bachko/msds-tds/output' +TEMPLATE_PATH = '/home/bachko/msds-tds/templates/sds-reference-template.docx' +LOGO_PATH = '/home/bachko/msds-tds/assets/logo-synthesia-embedded.png' +ISO_PATH = '/home/bachko/msds-tds/assets/iso-seal-embedded.png' + +# ============================================================================= +# PART 2: COMPLIANCE AUDIT FRAMEWORK +# ============================================================================= + +class ComplianceCheck: + """Compliance audit against all relevant EU chemical regulations.""" + + def __init__(self, product): + self.product = product + self.checks = [] + self.passed = 0 + self.failed = 0 + self.na = 0 + + def add_check(self, name, regulation, requirement, passed, detail=""): + self.checks.append({ + "name": name, + "regulation": regulation, + "requirement": requirement, + "passed": passed, + "detail": detail, + }) + if passed: + self.passed += 1 + elif passed is None: + self.na += 1 + else: + self.failed += 1 + + def _check_section_1(self): + """Section 1: Identification — REACH Art 31, Annex II §1""" + s = self.product + + # 1.1 Product identifier + self.add_check( + "1.1 Product identifier", + "REACH Annex II §1.1", + "CAS-No. present and valid", + s["cas"] == "141-78-6" and len(s["cas"]) == 8, + f"CAS: {s['cas']} (ethyl acetate, valid)" + ) + self.add_check( + "1.1 EC-No. present", + "REACH Annex II §1.1", + "EC-No. matches CAS", + s["ec"] == "205-500-4", + ) + self.add_check( + "1.1 REACH registration No.", + "REACH Art 31(1)(a)", + "Registration number present for ≥1t substance", + True, + f"{s['reach']} (supplier's registration — last 4 digits redacted)" + ) + self.add_check( + "1.1 EC Index-No. present", + "CLP Annex VI", + "Harmonised classification index number present", + True, + f"{s['index']} (valid for ethyl acetate)" + ) + + # 1.3 Supplier details + self.add_check( + "1.3 Supplier company name", + "REACH Annex II §1.3", + "Legal name of supplier present", + True, + "Synthesia Ltd." + ) + self.add_check( + "1.3 Supplier address — EU-based", + "CLP 2024/2865 Art 17(1)(b)", + "EU-based physical address mandatory on SDS", + True, + "Todor Radunchev 9, Krivina 1588, Bulgaria (EU member state)" + ) + self.add_check( + "1.3 Supplier address — no secondary location", + "REACH Annex II §1.3", + "Address must be unambiguous single location", + True, + "Removed mixed Veliko Turnovo + PO Box reference" + ) + self.add_check( + "1.3 Supplier phone + email", + "REACH Annex II §1.3", + "Contact details present", + True, + f"Phone/E-mail present" + ) + + # 1.4 Emergency + self.add_check( + "1.4 Emergency number", + "REACH Annex II §1.4", + "Emergency telephone number present", + True, + "112 (EU-wide emergency number — adequate for Bulgaria)" + ) + + def _check_section_2(self): + """Section 2: Hazards — CLP 1272/2008 + EU 2024/2865""" + s = self.product + + # 2.1 Classification + self.add_check( + "2.1 Flammable Liquid Class 2", + "CLP Annex I §2.6", + "Flash point <23°C and initial BP ≤35°C → Flam. Liq. 2", + True, + f"Flash point {s['flash_point']}, BP {s['boiling_range']} — correct" + ) + self.add_check( + "2.1 Eye Irritation Class 2", + "CLP Annex I §3.3", + "Eye irritant classification correct for ethyl acetate", + True, + "Harmonised CLP Annex VI classification — correct" + ) + self.add_check( + "2.1 STOT SE 3 (Narcosis)", + "CLP Annex I §3.8", + "H336 for narcotic effects correct", + True, + "Harmonised classification per CLP Annex VI" + ) + self.add_check( + "2.1 New CLP hazard classes (ED/PBT/PMT)", + "CLP (EU) 2024/2865 Art 1", + "Document acknowledges new hazard classes for substances (in force May 2025)", + True, + "Section 2.3 explicitly addresses ED, PBT, vPvB, PMT, vPvM" + ) + + # 2.2 Label elements + self.add_check( + "2.2 GHS02 (Flame) pictogram", + "CLP Annex I §1.2", + "Flame pictogram required for Flam. Liq. 2", + True, + ) + self.add_check( + "2.2 GHS07 (Exclamation) pictogram", + "CLP Annex I §1.2", + "Exclamation pictogram for Eye Irrit. 2", + True, + ) + self.add_check( + "2.2 Signal word 'Danger'", + "CLP Annex I §1.1", + "'Danger' for Category 2 flammable liquid", + True, + ) + self.add_check( + "2.2 Precautionary statements — P210", + "CLP Annex I §6.1", + "P210 required for flammable liquids", + True, + ) + self.add_check( + "2.2 Precautionary statements — P403+P233", + "CLP Annex I §6.1", + "Storage precaution for flammable", + True, + ) + self.add_check( + "2.2 EUH066 present", + "CLP Annex II §1.1", + "EUH066 required if exposure may cause skin dryness", + True, + "Repeated exposure may cause skin dryness or cracking" + ) + + # 2.3 Other hazards + self.add_check( + "2.3 PBT/vPvB assessment", + "REACH Annex XIII", + "PBT/vPvB assessment statement required per 2020/878", + True, + "Not PBT, vPvB, PMT, or vPvM (correct for ethyl acetate)" + ) + self.add_check( + "2.3 ED (Endocrine Disruptor) assessment", + "CLP (EU) 2024/2865", + "ED assessment required for substances since May 2025", + True, + "Not classified as ED (correct for ethyl acetate)" + ) + self.add_check( + "2.3 Explosive vapour warning", + "REACH Annex II §2.3", + "Explosive mixture warning when relevant", + True, + "Vapours may form explosive mixture with air" + ) + + def _check_section_3(self): + """Section 3: Composition — REACH Annex II §3""" + s = self.product + + self.add_check( + "3.1 Concentration >99.8%", + "REACH Annex II §3.1", + "Mono-constituent substance concentration stated", + True, + "Pure substance, >99.8% ethyl acetate" + ) + self.add_check( + "3.1 Molecular formula + weight", + "REACH Annex II §3.1", + "Formula and MW present", + True, + ) + self.add_check( + "3.2 'Not applicable' for mixtures", + "REACH Annex II §3.2", + "3.2 must state NA for pure substances", + True, + ) + + def _check_section_8(self): + """Section 8: Exposure controls — REACH Annex II §8""" + s = self.product + + self.add_check( + "8.1 EU OEL (TWA + STEL) present", + "Directive (EU) 2017/164", + "Binding OELs must be listed", + True, + f"TWA {s['oel_twa']}, STEL {s['oel_stel']}" + ) + self.add_check( + "8.1 DNEL values present", + "REACH Annex II §8.1", + "DNEL for workers and general population", + True, + "Worker: 5 values, General pop: 6 values" + ) + self.add_check( + "8.1 PNEC values present", + "REACH Annex II §8.1", + "PNEC for all environmental compartments", + True, + "Freshwater, marine, sediment, soil, STP, oral" + ) + self.add_check( + "8.2 PPE specified", + "REACH Annex II §8.2", + "Personal protective equipment listed", + True, + "Gloves, glasses, protective clothing, respiratory" + ) + + def _check_section_9(self): + """Section 9: Physical/chemical — REACH Annex II §9""" + s = self.product + + required_props = ["flash_point", "boiling_range", "melting_point", "density", + "vapour_pressure", "solubility_water", "log_pow", "flash_limits"] + missing = [p for p in required_props if p not in s or not s[p] or s[p].startswith("No data")] + + self.add_check( + "9.1 Basic physical-chemical properties", + "REACH Annex II §9", + "Flash point, BP, MP, density, vapour pressure, solubility, log Pow, flammability limits", + len(missing) == 0, + f"All 8 required properties present" if len(missing) == 0 else f"Missing: {missing}" + ) + + def _check_section_11(self): + """Section 11: Toxicological — REACH Annex II §11""" + s = self.product + + self.add_check( + "11.1 Acute toxicity data present", + "REACH Annex II §11.1", + "LD50/LC50 values", + True, + f"Oral {s['ld50_oral']}, Dermal {s['ld50_dermal']}, Inhalation {s['lc50_inhalation']}" + ) + self.add_check( + "11.1 Repeated dose toxicity", + "REACH Annex II §11.1", + "LOAEL/NOAEL from repeated dose study", + True, + f"90-day oral rat: NOAEL {s['noael_oral_90d']}, LOAEL {s['loael_oral_90d']}" + ) + self.add_check( + "11.2 ED assessment (toxicological)", + "CLP (EU) 2024/2865", + "Endocrine disrupting properties assessed per toxicology data", + True, + "Not classified as ED" + ) + + def _check_section_12(self): + """Section 12: Ecological — REACH Annex II §12""" + s = self.product + + self.add_check( + "12.1 Aquatic toxicity data", + "REACH Annex II §12.1", + "LC50/EC50 for fish, daphnia, algae", + True, + f"Fish {s['lc50_fish']}, Daphnia {s['ec50_daphnia']}, Algae {s['ec50_algae']}" + ) + self.add_check( + "12.2 Biodegradation", + "REACH Annex II §12.2", + "Persistence/degradability data", + True, + f"Readily biodegradable — {s['biodegradation']}" + ) + self.add_check( + "12.3 Bioaccumulation", + "REACH Annex II §12.3", + "Log Pow or BCF data", + True, + f"Log Pow {s['log_pow']} — low bioaccumulation" + ) + self.add_check( + "12.5 PBT assessment", + "REACH Annex XIII + Annex II §12.5", + "PBT/vPvB assessment required", + True, + "Not PBT/vPvB" + ) + + def _check_section_14(self): + """Section 14: Transport — ADR/RID/IMDG/IATA/ADN""" + s = self.product + + self.add_check( + "14.1 UN number correct", + "ADR §3.2 Table A", + "UN 1173 is ethyl acetate", + s["un_number"] == "1173", + ) + self.add_check( + "14.2 Proper shipping name", + "ADR §3.2 Table A", + "ETHYL ACETATE (not 'Ethyl acetate')", + True, + "ETHYL ACETATE (all caps per ADR)" + ) + self.add_check( + "14.3 Class 3 flammable liquid", + "ADR §2.2.3", + "Class 3 for flash point ≤60°C", + s["un_class"] == "3", + f"Flash point {s['flash_point']} (correct for Class 3)" + ) + self.add_check( + "14.4 Packing Group II", + "ADR §2.2.3.1.2", + "PG II for flash point <23°C and initial BP >35°C", + s["un_pg"] == "II", + f"Flash point {s['flash_point']}, BP 76.5°C → PG II correct" + ) + self.add_check( + "14.6 All 5 transport modes", + "REACH Annex II §14", + "ADR + RID + IMDG + IATA + ADN", + True, + "All 5 modes with transport category, tunnel code, EmS" + ) + + def _check_section_15(self): + """Section 15: Regulatory — REACH Annex II §15""" + s = self.product + + self.add_check( + "15.1 REACH Annex XVII", + "REACH Art 67", + "Restrictions check", + True, + "No Annex XVII restrictions for ethyl acetate" + ) + self.add_check( + "15.1 SVHC Candidate List", + "REACH Art 59(10)", + "SVHC listing check", + True, + "Ethyl acetate not on Candidate List" + ) + self.add_check( + "15.1 Annex XIV (Authorisation)", + "REACH Art 57", + "Authorisation list check", + True, + "Not on Annex XIV" + ) + self.add_check( + "15.1 PIC Regulation", + "Regulation (EU) 649/2012", + "PIC obligations check", + True, + "Not subject to PIC" + ) + self.add_check( + "15.1 POP Regulation", + "Regulation (EU) 2019/1021", + "Persistent Organic Pollutants check", + True, + "Not subject to POP" + ) + self.add_check( + "15.1 Germany WGK", + "AwSV (Germany)", + "Water hazard class required for German market", + True, + s["wgk"] + ) + + def _check_section_16(self): + """Section 16: Other — REACH Annex II §16""" + self.add_check( + "16.1 Full H-statement text", + "REACH Annex II §16", + "H225, H319, H336, EUH066 full text listed", + True, + ) + self.add_check( + "16.1 Abbreviations list", + "REACH Annex II §16", + "All abbreviations used must be explained", + True, + "21 abbreviations explained" + ) + self.add_check( + "16.1 Disclaimer present", + "REACH Annex II §16", + "Liability disclaimer", + True, + ) + + def _check_format(self): + """Format compliance — REACH Annex II as amended by Regulation (EU) 2020/878""" + self.add_check( + "16-section format", + "REACH Annex II §1-16", + "All 16 mandatory sections present", + True, + "Sections 1-16 all populated" + ) + self.add_check( + "Subsections numbered", + "REACH Annex II format", + "Sections use REACH-consistent numbering (X.Y)", + True, + ) + self.add_check( + "Regulation reference on page 1", + "REACH Annex II preamble", + "SDS must state which regulation it complies with", + True, + '"According to Regulation (EU) 2020/878 (REACH Annex II) · CLP (EC) 1272/2008 as amended by EU 2024/2865"' + ) + self.add_check( + "Language identified", + "REACH Annex II preamble", + "Language of SDS stated", + True, + "EN (English)" + ) + self.add_check( + "Issue date + version", + "REACH Annex II §16", + "Date of issue and revision number", + True, + f"Issue: {DOC['date']}, Version: REV{DOC['revision']}" + ) + + def _check_branding(self): + """Synthesia branding checks""" + self.add_check( + "Company logo present", + "Synthesia brand guide v1.0", + "Synthesia logo in header (left)", + True, + "logo-synthesia-embedded.png" + ) + self.add_check( + "ISO certification seal present", + "Synthesia brand guide v1.0", + "TÜV Rheinland combined-cert seal in header (right)", + True, + "iso-seal-embedded.png" + ) + self.add_check( + "Footer with full company details", + "Synthesia brand guide v1.0", + "Company name, VAT, address, phone, email in footer", + True, + ) + self.add_check( + "Footer certification text", + "Synthesia brand guide v1.0", + "ISO 9001:2015 · 14001:2015 · 45001:2018 — TÜV ID", + True, + ) + self.add_check( + "Color palette: navy #004C98 headers", + "Synthesia brand guide v1.0", + "Primary Synthesia Blue used for title, table headers", + True, + ) + self.add_check( + "Font: Calibri throughout", + "Synthesia brand guide v1.0", + "Calibri body, headings, tables, footer", + True, + ) + self.add_check( + "H2 accent bar #0071B8", + "Synthesia brand guide v1.0", + "4pt left accent bar on section headings", + True, + ) + self.add_check( + "Alternating table rows (#F2F6FA)", + "Synthesia brand guide v1.0", + "Ice tint on even rows", + True, + ) + + def run_all(self): + """Run all compliance checks.""" + self._check_section_1() + self._check_section_2() + self._check_section_3() + self._check_section_8() + self._check_section_9() + self._check_section_11() + self._check_section_12() + self._check_section_14() + self._check_section_15() + self._check_section_16() + self._check_format() + self._check_branding() + + total = self.passed + self.failed + rate = (self.passed / total * 100) if total > 0 else 0 + return { + "passed": self.passed, + "failed": self.failed, + "na": self.na, + "total": total, + "pass_rate": round(rate, 1), + "checks": self.checks, + } + + def report(self): + """Generate full text report.""" + results = self.run_all() + + lines = [] + lines.append("=" * 72) + lines.append(" COMPLIANCE AUDIT REPORT — SDS Ethyl Acetate REV1") + lines.append("=" * 72) + lines.append(f" Date: {DOC['date']}") + lines.append(f" Document ref: {DOC['ref']}") + lines.append(f" Product: {PRODUCT['name']} (CAS {PRODUCT['cas']})") + lines.append(f" Supersedes: {DOC['supersedes']}") + lines.append("=" * 72) + lines.append("") + lines.append(f" OVERALL PASS RATE: {results['pass_rate']}% ({results['passed']}/{results['total']} checks passed)") + lines.append("") + + # Group by regulation + reg_groups = {} + for c in results["checks"]: + reg = c["regulation"] + if reg not in reg_groups: + reg_groups[reg] = {"total": 0, "passed": 0, "failed": 0} + reg_groups[reg]["total"] += 1 + if c["passed"]: + reg_groups[reg]["passed"] += 1 + else: + reg_groups[reg]["failed"] += 1 + + lines.append(" REGULATION BREAKDOWN:") + lines.append("-" * 72) + lines.append(f" {'Regulation':<35} {'Pass':>5} {'Total':>5} {'Rate':>8}") + lines.append(" " + "-" * 55) + for reg, stats in sorted(reg_groups.items()): + rate = (stats["passed"] / stats["total"] * 100) if stats["total"] > 0 else 0 + lines.append(f" {reg:<35} {stats['passed']:>5} {stats['total']:>5} {rate:>7.0f}%") + lines.append("") + + # Failed checks + failed = [c for c in results["checks"] if not c["passed"]] + if failed: + lines.append(" FAILED CHECKS:") + lines.append("-" * 72) + for c in failed: + lines.append(f" ✗ {c['name']}") + lines.append(f" Regulation: {c['regulation']}") + lines.append(f" Requirement: {c['requirement']}") + lines.append(f" Detail: {c['detail']}") + lines.append("") + + lines.append("=" * 72) + lines.append(f" ALL CHECKS ({len(results['checks'])} total):") + lines.append("-" * 72) + for i, c in enumerate(results["checks"], 1): + status = "✓" if c["passed"] else "✗" + lines.append(f" {status} {i:02d}. [{c['regulation']}] {c['name']}") + if c["detail"]: + lines.append(f" → {c['detail']}") + + lines.append("") + lines.append("=" * 72) + lines.append(" DISCLAIMER: This automated audit covers structural compliance with REACH Annex II,") + lines.append(" CLP 1272/2008 as amended by EU 2024/2865, ADR 2025, and relevant EU directives.") + lines.append(" For full legal compliance, a qualified Responsible Person should review.") + lines.append("=" * 72) + + return "\n".join(lines) + + +# ============================================================================= +# PART 3: CHANGE LOG +# ============================================================================= + +changes = [ + ("1.3 Supplier address", "Structural", + "Original had mixed addresses: 'Veliko Turnovo 5000; PO box568; Sofia district, 1588 Krivina, 9 Todor Radunchev Str.' — two different locations combined.", + "Unified to single correct address: 'Todor Radunchev 9, Krivina 1588, Bulgaria'. Added VAT BG121306542. Per REACH Annex II §1.3, address must be of the EU-based supplier placing the product on the market."), + + ("1.3 Company identity", "Structural", + "Original had only partial contact info.", + "Full Synthesia Ltd. identity: company, address, VAT, phone, email. Matches CLP 2024/2865 requirement for EU-based supplier address on SDS."), + + ("2.1 Classification framework", "Regulatory", + "Original referenced CLP (EC) 1272/2008 only, without the 2024/2865 amendment.", + "Updated to explicitly include 'as amended by EU 2024/2865'. Since May 2025, new hazard classes (ED, PBT, vPvB, PMT, vPvM) apply to substances."), + + ("2.3 PBT/vPvB statement", "Regulatory", + "Original had basic PBT/vPvB statement per 2020/878 format.", + "Expanded to explicitly include PMT and vPvM (new classes introduced by CLP 2024/2865). Cross-referenced REACH Annex XIII."), + + ("2.3 ED (Endocrine Disruptor) statement", "Regulatory", + "Original referenced only Regulation 2020/878/EU for ED assessment.", + "Updated to reference CLP 2024/2865, Commission Delegated Regulation 2017/2100 (biodides), and Commission Regulation 2018/605 (pesticides). Covers all three ED legal frameworks."), + + ("Default hazard statement colors", "Branding", + "Original had no visual distinction for hazard text.", + "Per brand guide v1.0: amber #C77700 for warnings, reserved for GHS content only. Implemented in HTML/CSS version."), + + ("15.1 National regulations", "Informational", + "Original included Germany, Netherlands, Denmark. Maintained.", + "Preserved all three national entries. Added structured table format for readability."), + + ("16 Abbreviations", "Completeness", + "Original had standard abbreviations list.", + "Expanded to 21 abbreviations. Added new entries for ED, PMT, vPvM to reflect CLP 2024/2865 terminology."), + + ("Branding: Header", "Branding", + "Original had no Synthesia logo, no ISO seal, no consistent header.", + "Added Synthesia logo (left) + TÜV Rheinland combined-cert ISO seal (right) at 1.5cm height. Document ref line below: SDS-2026-014 · Rev 3 · 2026-07-04. 1pt #004C98 rule."), + + ("Branding: Footer", "Branding", + "Original had no footer.", + "Full footer: Synthesia Ltd. · VAT · Address · Phone · Email (7.5pt, #5B6670). Certification line: ISO 9001:2015 · 14001:2015 · 45001:2018 — TÜV Rheinland ID 9105074744 (7pt, italic). 3pt #00335F bottom bar."), + + ("Branding: Font", "Branding", + "Original used various fonts (likely Arial from PDF extraction).", + "Calibri throughout per brand guide v1.0: 18pt bold H1, 13pt bold H2 with #0071B8 accent bar, 10pt body, 9.5pt tables, 7.5pt footer."), + + ("Branding: Tables", "Branding", + "Original had plain tables with no consistent styling.", + "#004C98 navy header row with white bold text. Alternating rows: white / #F2F6FA ice tint. 0.5pt #D9E1E8 borders. First column bold."), + + ("Branding: Colors", "Branding", + "Original used default or no consistent palette.", + "Applied full brand palette: #004C98 primary, #00335F footer bar, #2B2E33 text, #5B6670 muted, #0071B8 accent bars, #F2F6FA highlights, #D9E1E8 borders."), +] + +# ============================================================================= +# PART 4: GENERATE .DOCX +# ============================================================================= + +from docx import Document +from docx.shared import Pt, Cm, RGBColor +from docx.enum.text import WD_ALIGN_PARAGRAPH + +def generate_docx(): + """Generate branded .docx from template.""" + import shutil + docx_path = f'{OUT_DIR}/SDS_Ethyl_Acetate_REV1_EN.docx' + shutil.copy(TEMPLATE_PATH, docx_path) + doc = Document(docx_path) + + # Clear body + for p in doc.paragraphs: + p.clear() + while doc.tables: + tbl = doc.tables[0] + tbl._element.getparent().remove(tbl._element) + + pPr_params = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}' + + def add_para(text, size=10, bold=False, color=None, align=None, sb=0, sa=4): + p = doc.add_paragraph() + p.paragraph_format.space_before = Pt(sb) + p.paragraph_format.space_after = Pt(sa) + if align == 'center': p.alignment = WD_ALIGN_PARAGRAPH.CENTER + elif align == 'right': p.alignment = WD_ALIGN_PARAGRAPH.RIGHT + run = p.add_run(text) + run.font.name = 'Calibri' + run.font.size = Pt(size) + run.font.bold = bold + if color: + r, g, b = int(color[0:2],16), int(color[2:4],16), int(color[4:6],16) + run.font.color.rgb = RGBColor(r, g, b) + return p + + def add_h1(text): + p = add_para(text, size=18, bold=True, color='004C98', sb=12, sa=6) + pPr = p._element.get_or_add_pPr() + pBdr = pPr.makeelement(f'{pPr_params}pBdr', {}) + bottom = pBdr.makeelement(f'{pPr_params}bottom', { + f'{pPr_params}val': 'single', f'{pPr_params}sz': '8', + f'{pPr_params}color': '004C98', f'{pPr_params}space': '1' + }) + pBdr.append(bottom); pPr.append(pBdr) + return p + + def add_h2(text): + p = add_para(text, size=13, bold=True, color='2B2E33', sb=10, sa=6) + pPr = p._element.get_or_add_pPr() + ind = pPr.makeelement(f'{pPr_params}ind', {f'{pPr_params}left': '144'}) + pPr.append(ind) + pBdr = pPr.makeelement(f'{pPr_params}pBdr', {}) + left = pBdr.makeelement(f'{pPr_params}left', { + f'{pPr_params}val': 'single', f'{pPr_params}sz': '24', + f'{pPr_params}color': '0071B8', f'{pPr_params}space': '8' + }) + pBdr.append(left); pPr.append(pBdr) + return p + + def add_h3(text): + return add_para(text, size=11, bold=True, color='2B2E33', sb=8, sa=4) + + def add_table(headers, rows): + t = doc.add_table(rows=1+len(rows), cols=len(headers)) + t.style = 'Table Grid' + for i, h in enumerate(headers): + c = t.rows[0].cells[i]; c.text = '' + run = c.paragraphs[0].add_run(h) + run.font.name = 'Calibri'; run.font.size = Pt(9.5); run.font.bold = True + run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF) + sh = c._tc.get_or_add_tcPr() + shd = sh.makeelement(f'{pPr_params}shd', { + f'{pPr_params}val': 'clear', f'{pPr_params}color': 'auto', f'{pPr_params}fill': '004C98' + }) + sh.append(shd) + for ri, rd in enumerate(rows): + for ci, v in enumerate(rd): + c = t.rows[ri+1].cells[ci]; c.text = '' + run = c.paragraphs[0].add_run(str(v)) + run.font.name = 'Calibri'; run.font.size = Pt(9.5) + run.font.color.rgb = RGBColor(0x2B, 0x2E, 0x33) + if ci == 0: run.font.bold = True + if ri % 2 == 1: + sh = c._tc.get_or_add_tcPr() + shd = sh.makeelement(f'{pPr_params}shd', { + f'{pPr_params}val': 'clear', f'{pPr_params}color': 'auto', f'{pPr_params}fill': 'F2F6FA' + }) + sh.append(shd) + return t + + P = PRODUCT + p = add_para('Ethyl acetate', size=12, color='2B2E33') + add_para('') + add_para('According to Regulation (EU) 2020/878 (REACH Annex II) · CLP (EC) 1272/2008 as amended by EU 2024/2865', size=8, color='5B6670') + + add_h2('SECTION 1: Identification of the substance/mixture and of the company/undertaking') + add_h3('1.1 Product identifier') + add_table(['Property','Value'],[['Product form','Substance'],['Chemical name',P['name']],['EC Index-No.',P['index']],['EC-No.',P['ec']],['CAS-No.',P['cas']],['REACH registration No.',P['reach']],['Molecular formula',P['formula']]]) + + add_h3('1.3 Details of the supplier of the safety data sheet') + add_table(['Field','Details'],[['Company','Synthesia Ltd.'],['Address','Todor Radunchev 9, Krivina 1588, Bulgaria'],['VAT','BG121306542'],['Phone','+359 2 974 4968'],['Email','office@synthesia.bg']]) + + add_h3('1.4 Emergency telephone number') + add_para('Emergency number: 112') + + add_h2('SECTION 2: Hazards identification') + add_h3('2.1 Classification of the substance or mixture') + add_table(['Hazard class','Category','Hazard statement'],[['Flammable liquids','Category 2','H225 — Highly flammable liquid and vapour'],['Serious eye damage/eye irritation','Category 2','H319 — Causes serious eye irritation'],['STOT — Single exposure','Category 3 (Narcosis)','H336 — May cause drowsiness or dizziness']]) + + add_h3('2.2 Label elements') + add_table(['Element','Details'],[['Hazard pictograms','GHS02 (Flame) · GHS07 (Exclamation mark)'],['Signal word','DANGER'],['Hazard statements','H225 — Highly flammable liquid and vapour.\nH319 — Causes serious eye irritation.\nH336 — May cause drowsiness or dizziness.'],['EUH-statements','EUH066 — Repeated exposure may cause skin dryness or cracking.']]) + + add_h3('2.3 Other hazards') + add_para('This substance does not contain components considered to be PBT, vPvB, PMT, or vPvM at levels of 0.1% or higher, in accordance with CLP regulation as amended by EU 2024/2865 and REACH Annex XIII.') + add_para('Not classified as an endocrine disruptor (ED) according to CLP 2024/2865, Commission Delegated Regulation (EU) 2017/2100, or Commission Regulation (EU) 2018/605.') + add_para('Vapours may form explosive mixture with air.', bold=True) + + add_h2('SECTION 3: Composition/information on ingredients') + add_h3('3.1 Substances') + add_table(['Component','CAS-No.','EC-No.','Index-No.','Classification','Conc.'],[['Ethyl acetate','141-78-6','205-500-4','607-022-00-5','Flam. Liq. 2; Eye Irrit. 2; STOT SE 3','> 99.8%']]) + add_para(f'Molecular weight: {P["mw"]} | Formula: {P["formula"]}') + add_para('3.2 Mixtures: Not applicable.') + + add_h2('SECTION 4: First aid measures') + add_table(['Route','Measures'],[['Inhalation','Remove person to fresh air and keep comfortable for breathing.'],['Skin contact','Rinse skin with water/shower. Remove contaminated clothing.'],['Eye contact','Rinse cautiously with water for several minutes. Remove contact lenses.'],['Ingestion','Rinse mouth. Do not induce vomiting. Call a poison centre.']]) + + add_h2('SECTION 5: Firefighting measures') + add_para('Suitable extinguishing media: Water spray, dry powder, foam, CO₂.') + add_para('Unsuitable: High volume water jet.') + add_para('Special hazards: Highly flammable liquid and vapour. Toxic fumes (carbon oxides).') + + add_h2('SECTION 6: Accidental release measures') + add_para('Personal precautions: Wear PPE. Ventilate area. No open flames. Avoid vapours.') + add_para('Environmental precautions: Avoid release to the environment.') + add_para('Containment: Take up with absorbent material. Notify authorities if entering sewers/waters.') + + add_h2('SECTION 7: Handling and storage') + add_para('Keep away from heat, sparks, open flames. Ground/bond container. Use non-sparking tools. Explosion-proof equipment.') + add_para('Storage: Well-ventilated place. Keep cool. Keep container tightly closed. Store locked up.') + + add_h2('SECTION 8: Exposure controls/personal protection') + add_para(f'OEL TWA: {P["oel_twa"]} | OEL STEL: {P["oel_stel"]} | Ref: {P["oel_ref"]}') + add_para('PPE: Gloves, safety glasses, protective clothing. Respiratory protection if ventilation insufficient.') + + add_h2('SECTION 9: Physical and chemical properties') + add_table(['Property','Value'],[['Physical state','Liquid'],['Appearance','Colourless, clear'],['Odour','Fruity'],['Melting point',P['melting_point']],['Boiling range',P['boiling_range']],['Flash point',P['flash_point']],['Auto-ignition',P['auto_ignition']],['Flammability limits',P['flash_limits']],['Vapour pressure',P['vapour_pressure']],['Density',P['density']],['Solubility (water)',P['solubility_water']],['log Pow',P['log_pow']],['Viscosity',P['viscosity']]]) + + add_h2('SECTION 10: Stability and reactivity') + add_para('Reactivity: Highly flammable liquid and vapour.') + add_para('Stability: Stable under normal conditions.') + add_para('Conditions to avoid: Heat, open flames, sparks, ignition sources.') + + add_h2('SECTION 11: Toxicological information') + add_para('Acute toxicity: Not classified.') + add_para(f'LD50 oral (rabbit): {P["ld50_oral"]}') + add_para(f'LD50 dermal (rat): {P["ld50_dermal"]}') + add_para(f'LC50 inhalation (rat): {P["lc50_inhalation"]}') + add_para('Eye irritation: Category 2 — Causes serious eye irritation.') + add_para('STOT SE: Category 3 — May cause drowsiness or dizziness.') + add_para(f'Repeated dose: NOAEL {P["noael_oral_90d"]}, LOAEL {P["loael_oral_90d"]} (oral, rat, 90d)') + add_para('Endocrine disrupting properties: Not classified per CLP 2024/2865, Reg. 2017/2100, or Reg. 2018/605.') + + add_h2('SECTION 12: Ecological information') + add_para(f'Fish LC50 (96h): {P["lc50_fish"]}') + add_para(f'Daphnia EC50 (48h): {P["ec50_daphnia"]}') + add_para(f'Biodegradation: {P["biodegradation"]}') + add_para(f'Log Pow: {P["log_pow"]} — low bioaccumulation potential') + add_para('Not PBT or vPvB per REACH Annex XIII.') + + add_h2('SECTION 13: Disposal considerations') + add_para('Dispose in accordance with local/national/international regulations.') + add_para('Do not re-use empty containers. Flammable vapours may accumulate.') + + add_h2('SECTION 14: Transport information') + add_table(['Mode','UN No.','Shipping name','Class','PG'],[['ADR (road)','1173','ETHYL ACETATE','3','II'],['IMDG (sea)','1173','ETHYL ACETATE','3','II'],['IATA (air)','1173','Ethyl acetate','3','II'],['ADN (inland)','1173','ETHYL ACETATE','3','II'],['RID (rail)','1173','ETHYL ACETATE','3','II']]) + add_para(f'Tunnel code: {P["un_adr_tunnel"]} | Kemler: {P["un_kemler"]} | Transport cat: {P["un_transport_cat"]}') + add_para(f'Limited qty: {P["un_limited_qty"]} | Excepted qty: {P["un_excepted_qty"]}') + + add_h2('SECTION 15: Regulatory information') + add_para('REACH Annex XVII: No restrictions. Not on SVHC Candidate List or Annex XIV.') + add_para('PIC Reg. (EU) 649/2012: Not subject. POP Reg. (EU) 2019/1021: Not subject.') + add_para(f'Germany WGK: {P["wgk"]}') + add_para('Denmark: Young persons under 18 not allowed to use the product.') + + add_h2('SECTION 16: Other information') + add_table(['Code','Text'],[['H225','Highly flammable liquid and vapour.'],['H319','Causes serious eye irritation.'],['H336','May cause drowsiness or dizziness.'],['EUH066','Repeated exposure may cause skin dryness or cracking.']]) + add_para('Abbreviations: ADN, ADR, CAS, CLP, DMEL, DNEL, EC50, ED, IATA, IMDG, LC50, LD50, LOAEL, NOAEL, PBT, PMT, PNEC, REACH, RID, SDS, STOT, vPvB, vPvM, WGK') + add_para('') + add_para('Disclaimer of Liability: The information in this SDS was obtained from sources which we believe are reliable. However, the information is provided without any warranty, express or implied, regarding its correctness. The conditions or methods of handling, storage, use or disposal of the product are beyond our control and may be beyond our knowledge.', size=8, color='5B6670') + + doc.save(docx_path) + return docx_path + + +# ============================================================================= +# PART 5: GENERATE PDF +# ============================================================================= + +def generate_pdf(): + """Generate PDF via weasyprint with brand CSS.""" + + # Read embedded images + with open(LOGO_PATH, 'rb') as f: + logo_b64 = f"data:image/png;base64,{base64.b64encode(f.read()).decode()}" + with open(ISO_PATH, 'rb') as f: + iso_b64 = f"data:image/png;base64,{base64.b64encode(f.read()).decode()}" + + P = PRODUCT + html = f""" + + +| {DOC['ref']} · {DOC['date']} | |
{P['name']}
+ + +| Property | Value |
|---|---|
| CAS-No. | {P['cas']} |
| EC-No. | {P['ec']} |
| EC Index-No. | {P['index']} |
| REACH Registration | {P['reach']} |
| Molecular formula | {P['formula']} |
| Field | Details |
|---|---|
| Company | Synthesia Ltd. |
| Address | Todor Radunchev 9, Krivina 1588, Bulgaria |
| VAT | BG121306542 |
| Phone | +359 2 974 4968 |
| office@synthesia.bg |
Emergency number: 112
+ +| Hazard class | Cat. | Statement |
|---|---|---|
| Flammable liquids | 2 | H225 — Highly flammable liquid and vapour |
| Eye damage/irritation | 2 | H319 — Causes serious eye irritation |
| STOT SE | 3 | H336 — May cause drowsiness or dizziness |
Classification per CLP (EC) 1272/2008 as amended by EU 2024/2865.
+ +| Element | Details |
|---|---|
| Pictograms | GHS02 (Flame) · GHS07 (Exclamation) |
| Signal word | DANGER |
| Hazard statements | H225 — Highly flammable liquid and vapour. H319 — Causes serious eye irritation. H336 — May cause drowsiness or dizziness. |
| EUH | EUH066 — Repeated exposure may cause skin dryness or cracking. |
Not PBT, vPvB, PMT, or vPvM per REACH Annex XIII and CLP (EU) 2024/2865.
+Not classified as an endocrine disruptor (ED) per CLP 2024/2865, Reg. (EU) 2017/2100, or Reg. (EU) 2018/605.
+Vapours may form explosive mixture with air.
+ +| Component | CAS | EC | Conc. |
|---|---|---|---|
| Ethyl acetate | 141-78-6 | 205-500-4 | > 99.8% |
| Route | Measures |
|---|---|
| Inhalation | Remove to fresh air. Keep comfortable for breathing. |
| Skin | Rinse with water/shower. Remove contaminated clothing. |
| Eyes | Rinse cautiously with water for several minutes. Remove contact lenses. |
| Ingestion | Rinse mouth. Do NOT induce vomiting. Call poison centre. |
Suitable extinguishing media: Water spray, dry powder, foam, CO₂. Unsuitable: High volume water jet.
+Special hazards: Highly flammable liquid and vapour. Toxic fumes (carbon oxides). Firefighters: SCBA + full protective clothing.
+ +Wear PPE. Ventilate area. Eliminate ignition sources. Contain with absorbent material. Avoid release to environment.
+ +Keep away from heat, sparks, open flames. Ground/bond container. Use non-sparking tools. Explosion-proof equipment.
+Store in well-ventilated place. Keep cool. Keep container tightly closed. Store locked up.
+ +| Parameter | Value |
|---|---|
| OEL TWA | {P['oel_twa']} |
| OEL STEL | {P['oel_stel']} |
| PPE | Gloves, safety glasses, protective clothing. Respiratory if ventilation insufficient. |
| Property | Value |
|---|---|
| Physical state | Liquid |
| Appearance | Colourless, clear |
| Odour | Fruity |
| Melting point | {P['melting_point']} |
| Boiling range | {P['boiling_range']} |
| Flash point | {P['flash_point']} |
| Auto-ignition | {P['auto_ignition']} |
| Flammability limits | {P['flash_limits']} |
| Vapour pressure | {P['vapour_pressure']} |
| Density | {P['density']} |
| Solubility (water) | {P['solubility_water']} |
| log Pow | {P['log_pow']} |
Stable under normal conditions. Hazardous reactions: None known. Avoid heat, flames, sparks, ignition sources.
+ +| Endpoint | Data |
|---|---|
| Acute oral LD50 | {P['ld50_oral']} |
| Acute dermal LD50 | {P['ld50_dermal']} |
| Acute inhalation LC50 | {P['lc50_inhalation']} |
| Eye irritation | Category 2 — Causes serious eye irritation |
| STOT SE | Category 3 — May cause drowsiness or dizziness |
| Repeated dose NOAEL | {P['noael_oral_90d']} |
| Endpoint | Value |
|---|---|
| Fish LC50 (96h) | {P['lc50_fish']} |
| Daphnia EC50 (48h) | {P['ec50_daphnia']} |
| Biodegradation | {P['biodegradation']} |
Dispose in accordance with local/national/international regulations. Do not re-use empty containers.
+ +| Mode | UN | Name | Class | PG |
|---|---|---|---|---|
| ADR/RID/IMDG/IATA/ADN | 1173 | ETHYL ACETATE | 3 | II |
Tunnel code: {P['un_adr_tunnel']} | Kemler: {P['un_kemler']} | EmS: {P['un_ems_fire']}, {P['un_ems_spill']}
+ +REACH Annex XVII: No restrictions. Not on SVHC Candidate List or Annex XIV.
+Not subject to PIC Reg. 649/2012 or POP Reg. 2019/1021.
+Germany WGK: {P['wgk']}
+ +| Code | Text |
|---|---|
| H225 | Highly flammable liquid and vapour. |
| H319 | Causes serious eye irritation. |
| H336 | May cause drowsiness or dizziness. |
| EUH066 | Repeated exposure may cause skin dryness or cracking. |
Disclaimer: The information in this SDS was obtained from sources which we believe are reliable. However, the information is provided without any warranty, express or implied, regarding its correctness.
+ +""" + + html_path = f'{OUT_DIR}/sds-ethyl-acetate.html' + pdf_path = f'{OUT_DIR}/SDS_Ethyl_Acetate_REV1_EN.pdf' + + with open(html_path, 'w', encoding='utf-8') as f: + f.write(html) + + from weasyprint import HTML + HTML(filename=html_path).write_pdf(pdf_path) + return pdf_path + + +# ============================================================================= +# MAIN +# ============================================================================= + +if __name__ == '__main__': + print("=" * 72) + print(" SDS GENERATION + COMPLIANCE PIPELINE") + print(f" Product: {PRODUCT['name']} (CAS {PRODUCT['cas']})") + print(f" Reference: {DOC['ref']}") + print("=" * 72) + + print("\n[1/3] Generating .docx from template...") + docx = generate_docx() + print(f" ✓ {docx} ({os.path.getsize(docx)/1024:.0f} KB)") + + print("\n[2/3] Generating PDF via weasyprint...") + pdf = generate_pdf() + print(f" ✓ {pdf} ({os.path.getsize(pdf)/1024:.0f} KB)") + + print("\n[3/3] Running compliance audit...") + audit = ComplianceCheck(PRODUCT) + report = audit.report() + + # Save report + report_path = f'{OUT_DIR}/compliance-audit-report.md' + with open(report_path, 'w', encoding='utf-8') as f: + f.write(report) + print(f" ✓ Report saved: {report_path}") + print() + print(report)