From e8d6e70f42fb8b5e99e94938a269e2807ec1af3c Mon Sep 17 00:00:00 2001 From: Jonas Bengtsson Date: Fri, 11 Sep 2026 23:41:47 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20Initial=20commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functional specification.md | 1384 +++++++++++++++++++++++++++++++++++ 1 file changed, 1384 insertions(+) create mode 100644 functional specification.md diff --git a/functional specification.md b/functional specification.md new file mode 100644 index 0000000..f22e3cc --- /dev/null +++ b/functional specification.md @@ -0,0 +1,1384 @@ +# Functional Specification + +## SCADA Unattended Change Tracker + +### 1. Purpose + +The purpose of the application is to provide automated version tracking of configuration and project files associated with a SCADA system. + +The application shall periodically inspect a configured set of files or directories for changes and automatically record detected changes in a Git repository. + +The resulting Git history shall provide an auditable record showing: + +* when changes were detected, +* which files were added, +* which files were modified, +* which files were removed, +* and, where applicable, who last modified each added or modified file. + +The application is intended to operate without normal user interaction and shall be capable of running on Windows, Linux and macOS. + +--- + +# 2. Scope + +The application shall: + +1. monitor one or more configured SCADA project directories; +2. identify file-system changes relative to the current Git repository state; +3. determine whether files have been: + + * added, + * modified, + * deleted, + * optionally renamed; +4. determine the last modifying user for added and modified files; +5. generate a structured Git commit message describing the detected changes; +6. stage the changes; +7. create a Git commit automatically; +8. maintain logs of application execution and errors; +9. support unattended scheduled execution; +10. operate consistently across supported operating systems. + +The initial implementation does not need to: + +* interpret the semantic meaning of SCADA configuration changes; +* restore files; +* approve or reject changes; +* provide a graphical user interface; +* automatically push commits to a remote Git repository. + +These functions may be added later. + +--- + +# 3. General Architecture + +The application should be divided into independent functional components. + +```text ++-------------------------+ +| Scheduler / Invocation | ++------------+------------+ + | + v ++-------------------------+ +| Application Controller | ++------------+------------+ + | + v ++-------------------------+ +| Repository Inspector | ++------------+------------+ + | + v ++-------------------------+ +| Change Detector | ++------------+------------+ + | + +-----+------+ + | | + v v ++-------------+ +----------------+ +| File Change | | Author Resolver| +| Information | | | ++------+------+ +-------+--------+ + | | + +-------+--------+ + | + v ++-------------------------+ +| Commit Message Builder | ++------------+------------+ + | + v ++-------------------------+ +| Git Commit Manager | ++------------+------------+ + | + v ++-------------------------+ +| Logging / Audit | ++-------------------------+ +``` + +The components should be loosely coupled so that SCADA-specific metadata extraction can be implemented independently of Git handling. + +--- + +# 4. Operating Modes + +The application shall support at least two operating modes. + +## 4.1 Run-once mode + +Example: + +```text +scada-change-tracker run +``` + +The application performs one complete inspection and exits. + +This mode is suitable for execution through: + +* Windows Task Scheduler, +* cron, +* systemd timers, +* CI/CD systems, +* Docker scheduled execution, +* other external schedulers. + +Run-once mode should be the primary operating mode because it simplifies reliability and cross-platform deployment. + +--- + +## 4.2 Scheduled service mode + +An optional internal scheduler may allow the application to remain running and execute according to configured times. + +Example configuration: + +```yaml +schedule: + enabled: true + times: + - "06:00" + - "12:00" + - "18:00" + - "23:30" +``` + +The application should use local system time unless a timezone is explicitly configured. + +Example: + +```yaml +timezone: Europe/Stockholm +``` + +--- + +# 5. Repository Configuration + +The application shall operate against an existing Git repository. + +Example: + +```yaml +repository: + path: "/path/to/scada/project" + branch: "main" +``` + +The configured directory shall contain a valid Git repository. + +Before attempting any modification, the application shall verify: + +* the directory exists; +* the directory is accessible; +* the directory is a Git repository; +* the configured branch can be determined; +* Git operations can be performed. + +If validation fails, the execution shall stop without modifying the repository. + +--- + +# 6. Change Detection + +## 6.1 Change comparison + +Changes shall be detected relative to the current Git HEAD. + +The following change types shall be supported: + +| Change | Identifier | +| ------------- | ---------- | +| Added file | `ADDED` | +| Modified file | `MODIFIED` | +| Deleted file | `DELETED` | +| Renamed file | `RENAMED` | + +Rename detection may initially be treated as one deletion and one addition if native rename detection is not implemented. + +--- + +## 6.2 Git status + +The application should use Git itself as the authoritative mechanism for determining changed files. + +The implementation should therefore use an equivalent of: + +```text +git status --porcelain +``` + +rather than independently comparing file timestamps. + +This avoids false change detection caused by modification times alone. + +--- + +# 7. File Inclusion and Exclusion + +The application shall support configurable inclusion and exclusion rules. + +Example: + +```yaml +files: + include: + - "**/*" + + exclude: + - "**/*.tmp" + - "**/*.log" + - "**/~*" + - ".git/**" + - "runtime/**" + - "cache/**" +``` + +Glob-style matching should be supported. + +Files excluded by configuration shall neither be committed nor included in commit messages. + +--- + +# 8. Last Modifier Identification + +## 8.1 Requirement + +For every: + +* added file; +* modified file; + +the application shall attempt to determine the person or account responsible for its most recent modification. + +Example: + +```text +Modified: + configuration/plant1.xml + Last modified by: DOMAIN\jsmith +``` + +Deleted files do not require a last-modifier lookup because the original file may no longer be available. + +--- + +# 9. Author Resolution + +Determining the last modifying user shall be implemented as a separate abstraction. + +Conceptually: + +```python +class AuthorResolver: + def resolve(file_path) -> AuthorResult: + ... +``` + +A result should contain at least: + +```text +name +identifier +source +confidence +timestamp +``` + +Example: + +```json +{ + "name": "John Smith", + "identifier": "DOMAIN\\jsmith", + "source": "scada_metadata", + "confidence": "authoritative", + "timestamp": "2026-09-11T14:31:22+02:00" +} +``` + +--- + +# 10. Author Resolver Strategies + +The application shall support configurable resolver implementations. + +Suggested resolver types are: + +### SCADA metadata resolver + +Reads user information embedded in the SCADA project file. + +This should be preferred when the SCADA platform records information such as: + +* last modified by; +* engineering user; +* operator; +* change timestamp; +* workstation; +* project revision. + +--- + +### Companion metadata resolver + +Reads metadata associated with the file. + +For example: + +```text +pumpstation.xml +pumpstation.xml.metadata +``` + +or from a project database. + +--- + +### SCADA audit-log resolver + +Looks up the changed file or object in the SCADA system's audit log. + +This is likely to provide the strongest attribution where the SCADA system maintains authenticated engineering change records. + +--- + +### Operating-system resolver + +An OS-specific resolver may be implemented if the environment provides authoritative file auditing. + +File ownership alone shall **not** be interpreted as proof of the last modifying user. + +For example, on Windows: + +```text +DOMAIN\SCADAService +``` + +could own the file even though another engineering user performed the modification. + +--- + +### Unknown resolver + +If no reliable identity can be determined: + +```text +Last modified by: UNKNOWN +``` + +The application shall still create the commit unless configured otherwise. + +--- + +# 11. Resolver Priority + +Multiple author resolvers may be configured. + +Example: + +```yaml +author_resolution: + resolvers: + - scada_metadata + - scada_audit_log + - sidecar_metadata + + fallback: unknown +``` + +The resolvers shall execute in configured priority order. + +The first authoritative result shall be used. + +--- + +# 12. Change Data Model + +Each detected change should internally be represented using a structure similar to: + +```text +ChangeRecord + +path +change_type +previous_path +size +file_timestamp +author +author_source +author_timestamp +``` + +For example: + +```json +{ + "path": "Stations/PS101/config.xml", + "change_type": "MODIFIED", + "previous_path": null, + "size": 34127, + "file_timestamp": "2026-09-11T13:44:12+02:00", + "author": "DOMAIN\\jsmith", + "author_source": "scada_audit_log", + "author_timestamp": "2026-09-11T13:43:58+02:00" +} +``` + +--- + +# 13. Commit Generation + +If no relevant files have changed, the application shall: + +1. record the execution in its log; +2. not create an empty Git commit; +3. return a successful execution result. + +Example log: + +```text +2026-09-11 18:00:02 INFO No SCADA changes detected. +``` + +--- + +# 14. Git Staging + +When changes are detected the application shall: + +1. collect the complete change set; +2. resolve author information; +3. generate the commit message; +4. stage the relevant files; +5. verify the staged change set; +6. create the Git commit. + +Files outside the configured scope shall not be staged. + +The application should avoid blindly executing: + +```text +git add --all +``` + +unless the repository is exclusively dedicated to tracked SCADA data. + +--- + +# 15. Commit Message Format + +Commit messages shall be human-readable while retaining a predictable structure that can later be parsed automatically. + +Recommended format: + +```text +SCADA automatic change capture - 2026-09-11 18:00:03 + +Summary: + Added: 2 + Modified: 3 + Deleted: 1 + Renamed: 0 + +Added: + Stations/PS101/pump2.xml + Last modified by: DOMAIN\jsmith + Modified at: 2026-09-11 15:41:22 + + Stations/PS104/settings.xml + Last modified by: DOMAIN\adoe + Modified at: 2026-09-11 16:02:14 + +Modified: + Stations/PS101/project.xml + Last modified by: DOMAIN\jsmith + Modified at: 2026-09-11 15:42:09 + + Stations/PS103/alarm.xml + Last modified by: DOMAIN\adoe + Modified at: 2026-09-11 16:13:54 + + System/global.xml + Last modified by: UNKNOWN + +Deleted: + Stations/PS027/old-config.xml +``` + +--- + +# 16. Commit Subject + +The first commit line should be concise. + +Recommended format: + +```text +SCADA automatic change capture - YYYY-MM-DD HH:MM:SS +``` + +Alternative: + +```text +SCADA: 2 added, 3 modified, 1 deleted +``` + +The detailed information shall be placed in the commit body. + +--- + +# 17. Git Commit Identity + +The Git commit author shall represent the automated tracking system rather than the person who changed an individual file. + +Example: + +```yaml +git: + user_name: "SCADA Change Tracker" + user_email: "scada-change-tracker@localhost" +``` + +The engineers responsible for individual changes are instead recorded within the commit message. + +This avoids incorrectly assigning a single engineer as the author of a commit containing changes made by several people. + +--- + +# 18. Multiple Authors + +One execution may contain changes made by multiple individuals. + +Example: + +```text +Modified: + plant1.xml + Last modified by: DOMAIN\jsmith + + plant2.xml + Last modified by: DOMAIN\adoe +``` + +The application shall therefore store attribution per file rather than per commit. + +--- + +# 19. Atomic Processing + +A commit shall represent one complete collection cycle. + +Conceptually: + +```text +Start collection + ↓ +Detect all changes + ↓ +Resolve metadata + ↓ +Build complete change record + ↓ +Stage changes + ↓ +Validate staged state + ↓ +Commit + ↓ +Finish collection +``` + +The application shall not create multiple commits for one collection unless explicitly configured to do so. + +--- + +# 20. Concurrent Changes + +Files may be modified while the collection is taking place. + +The application should therefore detect this situation. + +For each file the application may record attributes before and after processing: + +```text +size +modification timestamp +optional content hash +``` + +If the file changes while being processed, the application shall either: + +1. restart analysis for that file; or +2. abort the complete commit and retry during the next execution. + +The default behaviour should favour data integrity over forcing a commit. + +--- + +# 21. Repository Lock + +Only one tracker execution shall be allowed against a repository at the same time. + +The application shall implement a repository-level execution lock. + +For example: + +```text +.scada-change-tracker.lock +``` + +The lock shall include information such as: + +```text +process_id +hostname +start_time +``` + +Stale locks shall be detected safely. + +--- + +# 22. Logging + +Application activity shall be logged independently of Git. + +Minimum log information shall include: + +```text +execution start +execution completion +repository +number of detected changes +files processed +author resolution result +Git operations +warnings +errors +commit hash +execution duration +``` + +Example: + +```text +2026-09-11 18:00:01 INFO Starting SCADA change collection +2026-09-11 18:00:01 INFO Repository: D:\SCADA\Project +2026-09-11 18:00:02 INFO Detected 6 changes +2026-09-11 18:00:02 INFO Author resolved: Stations/PS101/project.xml -> DOMAIN\jsmith +2026-09-11 18:00:03 INFO Commit created: 93ab4e21 +2026-09-11 18:00:03 INFO Collection completed +``` + +--- + +# 23. Log Rotation + +File-based logging shall support rotation. + +Example: + +```yaml +logging: + file: "logs/scada-change-tracker.log" + max_size_mb: 20 + backup_count: 10 +``` + +Console logging shall also be supported. + +--- + +# 24. Error Handling + +Errors shall be classified. + +Recommended categories: + +```text +CONFIGURATION_ERROR +REPOSITORY_ERROR +FILE_ACCESS_ERROR +AUTHOR_RESOLUTION_ERROR +GIT_ERROR +LOCK_ERROR +INTERNAL_ERROR +``` + +An author-resolution error shall normally not prevent a commit. + +For example: + +```text +Author: UNKNOWN +Reason: Audit log unavailable +``` + +A Git or repository integrity error shall prevent the commit. + +--- + +# 25. Exit Codes + +Suggested process exit codes: + +| Code | Meaning | +| ---: | --------------------------- | +| 0 | Successful execution | +| 1 | General application failure | +| 2 | Configuration error | +| 3 | Repository error | +| 4 | Git operation failure | +| 5 | Repository locked | +| 6 | Change collection failed | + +This makes the application suitable for external monitoring. + +--- + +# 26. Configuration + +Configuration should primarily be stored in YAML. + +Example: + +```yaml +application: + timezone: Europe/Stockholm + +repository: + path: "D:/SCADA/Project" + branch: main + +git: + user_name: "SCADA Change Tracker" + user_email: "scada-change-tracker@localhost" + +files: + include: + - "**/*" + + exclude: + - "**/*.tmp" + - "**/*.log" + - ".git/**" + +author_resolution: + resolvers: + - scada_metadata + - scada_audit_log + + fallback: unknown + +commit: + create_when_no_changes: false + +logging: + level: INFO + console: true + file: "logs/scada-change-tracker.log" +``` + +Environment variables should be capable of overriding sensitive or deployment-specific settings. + +--- + +# 27. Cross-Platform Requirements + +The project shall support: + +* Windows, +* Linux, +* macOS. + +The implementation shall therefore avoid assumptions about: + +* path separators; +* shell syntax; +* drive letters; +* filesystem ownership models; +* username formats; +* case sensitivity. + +Python's: + +```text +pathlib +``` + +shall be preferred for filesystem paths. + +Shell command strings should not be constructed manually where avoidable. + +For subprocess execution, argument arrays should be used. + +Conceptually: + +```python +subprocess.run( + ["git", "status", "--porcelain"], + ... +) +``` + +rather than: + +```python +os.system("git status --porcelain") +``` + +--- + +# 28. Git Integration + +The Git integration may use either: + +* the Git CLI through `subprocess`; or +* a Python Git library. + +Using the Git CLI is recommended initially because it closely follows native Git behaviour and makes troubleshooting straightforward. + +The Git executable shall therefore be treated as an external prerequisite. + +At startup the application shall verify: + +```text +git --version +``` + +and fail gracefully if Git is unavailable. + +--- + +# 29. Python Version + +Recommended minimum: + +```text +Python >= 3.12 +``` + +The application should avoid platform-specific Python dependencies unless they are isolated behind optional adapters. + +--- + +# 30. Command-Line Interface + +Suggested commands: + +```text +scada-change-tracker run +scada-change-tracker status +scada-change-tracker validate +scada-change-tracker config +``` + +### `run` + +Perform change collection and create a commit if necessary. + +### `status` + +Display currently detected changes without staging or committing them. + +### `validate` + +Validate: + +* configuration, +* Git installation, +* repository, +* file access, +* configured author resolvers. + +### `config` + +Display the effective configuration with secrets redacted. + +--- + +# 31. Dry-Run Mode + +The application shall support: + +```text +scada-change-tracker run --dry-run +``` + +Dry-run mode shall perform: + +```text +change detection +author resolution +commit message generation +validation +``` + +but shall not: + +```text +stage files +create commits +push data +modify the repository +``` + +The generated commit message should be displayed. + +--- + +# 32. Security + +The application shall follow least-privilege principles. + +The execution account should require only: + +* read access to source metadata; +* read/write access to the tracked repository; +* access required to query SCADA audit information. + +SCADA engineering credentials shall not be embedded in source code. + +Secrets shall be provided through: + +* environment variables; +* operating-system secret stores; +* external secret-management systems. + +Secrets must never appear in Git commit messages or application logs. + +--- + +# 33. Sensitive File Protection + +The application should support rules preventing accidental versioning of sensitive data. + +Example: + +```yaml +security: + forbidden_patterns: + - "**/*.key" + - "**/*.pem" + - "**/secrets.*" + - "**/credentials.*" +``` + +If such a file is detected, the default behaviour should be to abort the commit and log a security warning. + +--- + +# 34. Remote Repository + +Remote synchronization shall be optional. + +Future configuration could contain: + +```yaml +remote: + enabled: true + name: origin + push_after_commit: true +``` + +A failed push shall not invalidate the locally created commit. + +The application shall distinguish: + +```text +COMMIT_SUCCESS +PUSH_FAILURE +``` + +--- + +# 35. Audit Information + +Each collection should internally generate an execution identifier. + +For example: + +```text +01J7K8HYV84ZKFH1J4T9R8DZQN +``` + +The identifier may be included in the commit: + +```text +Tracker-Run: 01J7K8HYV84ZKFH1J4T9R8DZQN +``` + +This provides traceability between: + +* application logs; +* Git commits; +* external monitoring; +* SCADA audit records. + +--- + +# 36. Structured Commit Metadata + +To simplify future machine processing, the end of the commit message may include structured trailers. + +Example: + +```text +Tracker-Version: 1.0.0 +Tracker-Run: 01J7K8HYV84ZKFH1J4T9R8DZQN +Tracker-Host: SCADA-SRV-01 +Tracker-Changes: 6 +``` + +This enables later processing without parsing the human-readable sections. + +--- + +# 37. Functional Requirements + +## FR-001 – Repository inspection + +The system shall inspect a configured Git repository for uncommitted file changes. + +## FR-002 – Added files + +The system shall identify newly added files. + +## FR-003 – Modified files + +The system shall identify modified files. + +## FR-004 – Deleted files + +The system shall identify deleted files. + +## FR-005 – Rename detection + +The system should identify renamed files where practical. + +## FR-006 – Author identification + +The system shall attempt to determine the last modifying identity for every added and modified file. + +## FR-007 – Unknown author + +The system shall support an `UNKNOWN` author state. + +## FR-008 – Per-file attribution + +Author information shall be associated with individual files rather than the complete commit. + +## FR-009 – Commit generation + +The system shall automatically generate a Git commit for detected changes. + +## FR-010 – Commit summary + +The commit message shall contain counts for each change type. + +## FR-011 – Commit details + +The commit message shall list every affected file. + +## FR-012 – Attribution + +Added and modified files shall contain last-modifier information in the commit message. + +## FR-013 – Deleted files + +Deleted files shall be listed without requiring modifier information. + +## FR-014 – Empty executions + +The system shall not create an empty commit when no changes are detected. + +## FR-015 – Logging + +Every execution shall produce an audit log. + +## FR-016 – Cross-platform support + +The system shall operate on Windows, Linux and macOS. + +## FR-017 – Dry run + +The system shall support change analysis without repository modification. + +## FR-018 – Configuration + +Application behaviour shall be configurable without modifying source code. + +## FR-019 – File filters + +The system shall support file inclusion and exclusion patterns. + +## FR-020 – Concurrency protection + +The system shall prevent simultaneous tracker executions against the same repository. + +## FR-021 – Error isolation + +Failure to identify an author shall not normally prevent an otherwise valid change from being committed. + +## FR-022 – Repository protection + +Git, filesystem or repository integrity errors shall prevent commit creation. + +## FR-023 – Atomic collection + +A normal execution shall produce at most one commit representing the complete detected change set. + +## FR-024 – Sensitive-data protection + +Configured forbidden files shall not automatically be committed. + +--- + +# 38. Suggested Python Package Structure + +```text +scada-change-tracker/ +│ +├── pyproject.toml +├── README.md +├── LICENSE +│ +├── config/ +│ └── example.yaml +│ +├── src/ +│ └── scada_change_tracker/ +│ │ +│ ├── __init__.py +│ ├── __main__.py +│ ├── cli.py +│ ├── config.py +│ ├── application.py +│ │ +│ ├── git/ +│ │ ├── repository.py +│ │ ├── status.py +│ │ └── commit.py +│ │ +│ ├── changes/ +│ │ ├── detector.py +│ │ ├── models.py +│ │ └── filters.py +│ │ +│ ├── authors/ +│ │ ├── base.py +│ │ ├── resolver.py +│ │ ├── unknown.py +│ │ └── scada/ +│ │ └── ... +│ │ +│ ├── commits/ +│ │ └── message_builder.py +│ │ +│ ├── security/ +│ │ └── validator.py +│ │ +│ ├── locking/ +│ │ └── repository_lock.py +│ │ +│ └── logging/ +│ └── setup.py +│ +└── tests/ + ├── unit/ + ├── integration/ + └── fixtures/ +``` + +--- + +# 39. Core Domain Objects + +The project should initially define the following central objects: + +```text +Repository +ChangeSet +ChangeRecord +AuthorIdentity +AuthorResolution +TrackerRun +CommitResult +``` + +A `ChangeSet` conceptually contains: + +```text +ChangeSet + ├── added[] + ├── modified[] + ├── deleted[] + └── renamed[] +``` + +Each item is represented by a `ChangeRecord`. + +--- + +# 40. Processing Sequence + +A normal execution shall approximately perform the following sequence: + +```text +1. Load configuration +2. Validate configuration +3. Acquire repository lock +4. Verify Git availability +5. Validate repository +6. Determine current repository status +7. Apply inclusion/exclusion rules +8. Create ChangeSet +9. Resolve authors for ADDED files +10. Resolve authors for MODIFIED files +11. Validate files against security rules +12. Generate commit message +13. Stage selected changes +14. Verify staged changes +15. Create commit +16. Record commit hash +17. Write audit result +18. Release lock +19. Exit +``` + +If no changes exist, execution proceeds directly from step 8 to audit logging and termination. + +--- + +# 41. Testing Requirements + +Tests should cover at minimum: + +### Change detection + +* new file; +* modified file; +* deleted file; +* rename; +* multiple simultaneous changes; +* Unicode filenames; +* filenames containing spaces. + +### Git + +* clean repository; +* dirty repository; +* invalid repository; +* failed commit; +* unavailable Git executable. + +### Author resolution + +* one successful resolver; +* multiple resolver fallback; +* unknown user; +* unavailable audit source; +* malformed SCADA metadata. + +### File handling + +* inaccessible file; +* file removed during collection; +* file modified during collection; +* excluded file; +* forbidden file. + +### Cross-platform + +Automated testing should run against at least: + +```text +Windows +Linux +``` + +with macOS included where practical. + +A CI test matrix is recommended. + +--- + +# 42. Future Functional Extensions + +The architecture should permit future introduction of: + +* automatic push to central Git server; +* signed Git commits; +* commit signing using a machine identity; +* SCADA semantic comparison; +* XML-aware comparison; +* JSON-aware comparison; +* proprietary SCADA project parsers; +* alarm configuration comparison; +* PLC source comparison; +* automatic reports; +* REST API; +* web interface; +* Grafana integration; +* email/Teams notifications; +* change approval workflow; +* correlation against maintenance or change requests; +* integration with Active Directory; +* integration with SCADA audit logs; +* cryptographic file hashes; +* asset/reference-designation correlation; +* automatic mapping of files to IEC/ISO 81346 objects; +* detection of changes outside approved maintenance windows. + +--- + +# 43. Important Design Principle + +The application shall distinguish between three separate concepts: + +```text +Git commit author + ≠ +File last modifier + ≠ +SCADA change originator +``` + +The Git commit author is the automated service. + +The file last modifier is information obtained from the best available metadata source. + +The actual SCADA change originator should only be stated when an authoritative source, such as the SCADA audit trail, provides that information. + +The application shall not infer a human change originator merely from filesystem ownership. + +--- + +# 44. Definition of Done – Initial Release + +Version 1.0 can be considered complete when it can: + +1. run on Windows and Linux; +2. inspect an existing Git repository; +3. detect added, modified and deleted files; +4. filter files through configurable include/exclude rules; +5. invoke a configurable author resolver; +6. record per-file author information for additions and modifications; +7. generate the defined structured commit message; +8. automatically stage and commit changes; +9. avoid empty commits; +10. provide dry-run functionality; +11. produce rotating application logs; +12. prevent concurrent execution; +13. return useful process exit codes; +14. safely handle unresolved authors; +15. execute unattended through an external scheduler. + +The initial implementation should deliberately keep **SCADA-specific change attribution behind the `AuthorResolver` interface**. That makes the generic Git/change-tracking engine reusable while allowing a resolver tailored to the actual SCADA platform to be added independently.