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 platformcrate
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
clicommand. 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
Taskentity so that theTask.Statusis set tofailed. - Can the task tolerate partial failures?
- If so, add errors to the
Taskentity to debug recoverable errors during a task run. - If not, set the error message on the
Taskentity so that theTask.Statusis set tofailed.
- If so, add errors to the
- Should affected entities maintain a reference to
Taskinstances?- If so, add
task_refsentries to entities affected by a run of aTaskProviderinstance.
- If so, add