Design Guidelines
The following sections contain a non-exhaustive list of design guidelines to consider when contributing to Harbor. Suggestions for additional guiding principles welcome!
Repository Organization
root/
├── api/ # HTTP API
├── cli/ # Enrichment Engine
├── extensions/ # Custom logic specific to a Harbor instance
└── sdk/ # Automation and developer oriented tooling
├── core/ # Component Model and Domain Logic
└── platform/ # Infrastructure and generically reusable code
Modules
Subdirectories are the unit of modularization in Rust. They should contain a mod.rs
file and this
file should contain exports, unit tests, and types that are shared or fundamental to the module as
a whole.
Examples of fundamental types include:
- Enums
- Traits
- Errors
Platform
Code in the platform
crate is intended to be entirely generic and unrelated to the Harbor
application. It should be thought of as a separate reusable library that can be leveraged by any
application. When contributing or reviewing new features or modifications to the platform
crate
it is imperative to keep this in mind.
Services
- Services can consume external models or types but should not expose them outside the crate boundary. Make sure your service exposes only Harbor entities outside the crate.
- If a function does not rely on shared state, consider making it a module level function instead. It will likely be easier to test.
- If you need to repeatedly use a type that is expensive to create, such as an TLS-enabled HTTP Client or a DB driver that establishes long-lived connections, consider wrapping it in a service.
Task Providers
Some specific things to consider when designing a TaskProvider
are:
- What kind of task is it?
- Can one of the existing enumerations be extended or is it an altogether new thing?
- Tasks typically map to a
cli
command. Does the new task naturally fit under an existing command or is a new command needed?
- If you experience and unrecoverable error, make sure to set the error message on the
Task
entity so that theTask.Status
is set tofailed
. - Can the task tolerate partial failures?
- If so, add errors to the
Task
entity to debug recoverable errors during a task run. - If not, set the error message on the
Task
entity so that theTask.Status
is set tofailed
.
- If so, add errors to the
- Should affected entities maintain a reference to
Task
instances?- If so, add
task_refs
entries to entities affected by a run of aTaskProvider
instance.
- If so, add