Final cleanup before beginning the MVP implementation
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,7 @@
|
||||
# distributor binary and testing workspace
|
||||
/distributor
|
||||
/workspace
|
||||
|
||||
# ---> Go
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
@@ -49,6 +53,7 @@ go.work.sum
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
# go-application-template
|
||||
# distributor
|
||||
|
||||
`distributor` is a planned Go application for validating and publishing manifested Markdown bundles.
|
||||
|
||||
Implementation has not started yet. Current design and implementation planning lives under `docs/roadmap/`.
|
||||
|
||||
@@ -477,7 +477,7 @@ pipelines:
|
||||
destinations:
|
||||
- id: markdown-archive
|
||||
backend: s3
|
||||
endpoint: https://s3.maximumdirect.net
|
||||
endpoint: https://s3.example.com
|
||||
bucket: reports
|
||||
prefix: weather/archive
|
||||
region: us-east-1
|
||||
@@ -491,7 +491,7 @@ pipelines:
|
||||
|
||||
- id: static-site
|
||||
backend: ssh
|
||||
uri: ssh://deploy@web.maximumdirect.net:22
|
||||
uri: ssh://deploy@web.example.com:22
|
||||
path: /srv/www/weather
|
||||
publish:
|
||||
source: false
|
||||
@@ -514,7 +514,7 @@ pipelines:
|
||||
destinations:
|
||||
- id: private-markdown-archive
|
||||
backend: s3
|
||||
endpoint: https://s3.maximumdirect.net
|
||||
endpoint: https://s3.example.com
|
||||
bucket: reports
|
||||
prefix: dnd/session-recaps
|
||||
region: us-east-1
|
||||
|
||||
@@ -36,12 +36,12 @@ A source bundle is a directory containing a `manifest.json` file. For MVP, the m
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "weather.daily.brentwood.2026-05-30",
|
||||
"digest": "sha256:...",
|
||||
"digest": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"created": "2026-05-30T11:10:00Z",
|
||||
"files": [
|
||||
{
|
||||
"path": "report.md",
|
||||
"sha256": "sha256:...",
|
||||
"sha256": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"size": 12345
|
||||
}
|
||||
]
|
||||
@@ -168,12 +168,12 @@ A destination bundle path is considered distributor-managed only when it contain
|
||||
"manifest": {
|
||||
"schema_version": 1,
|
||||
"id": "weather.daily.brentwood.2026-05-30",
|
||||
"digest": "sha256:...",
|
||||
"digest": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"created": "2026-05-30T11:10:00Z",
|
||||
"files": [
|
||||
{
|
||||
"path": "report.md",
|
||||
"sha256": "sha256:...",
|
||||
"sha256": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"size": 12345
|
||||
}
|
||||
]
|
||||
@@ -185,7 +185,7 @@ A destination bundle path is considered distributor-managed only when it contain
|
||||
"kind": "generated",
|
||||
"source_path": "report.md",
|
||||
"transform": "markdown_to_html",
|
||||
"sha256": "sha256:...",
|
||||
"sha256": "sha256:3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"size": 23456
|
||||
}
|
||||
]
|
||||
|
||||
@@ -29,7 +29,9 @@ File paths:
|
||||
- must not contain backslashes;
|
||||
- must not resolve outside the backend root.
|
||||
|
||||
Prefix paths use the same slash-separated model. A prefix may be empty to represent the backend root for listing and destination emptiness checks.
|
||||
Prefix paths use the same slash-separated model. A prefix may be empty to represent the backend root for traversal and destination emptiness checks.
|
||||
|
||||
Prefix matching must preserve logical path boundaries. A prefix of `foo` matches `foo` and entries below `foo/`; it must not match a sibling path such as `foobar`. Backends that map logical paths to object keys must apply the same normalized boundary rule after combining configured backend prefixes with caller-provided logical prefixes.
|
||||
|
||||
Backends own conversion from logical paths to native paths or object keys. Core packages should not construct local filesystem paths, SFTP paths, or S3 object keys directly.
|
||||
|
||||
@@ -54,6 +56,34 @@ Byte helpers are expected to cover manifests, destination state, small source ar
|
||||
|
||||
Write operations should create required parent directories or prefixes as needed.
|
||||
|
||||
Concrete option and callback types should use this shape:
|
||||
|
||||
```go
|
||||
type WalkOptions struct {
|
||||
Recursive bool
|
||||
Limit int
|
||||
}
|
||||
|
||||
type WalkFunc func(Entry) error
|
||||
|
||||
var ErrStopWalk = errors.New("stop walk")
|
||||
|
||||
type WriteOptions struct {
|
||||
ContentType string
|
||||
Overwrite bool
|
||||
PreferAtomic bool
|
||||
Size int64
|
||||
SizeKnown bool
|
||||
}
|
||||
|
||||
type DeleteOptions struct {
|
||||
IgnoreMissing bool
|
||||
PruneEmptyDirs bool
|
||||
}
|
||||
```
|
||||
|
||||
`WalkOptions.Limit == 0` means no explicit limit. `SizeKnown` applies primarily to `WriteFrom`; byte writes can infer size from the provided data.
|
||||
|
||||
## Entries and Metadata
|
||||
|
||||
Storage metadata should be represented by an `Entry` model with at least:
|
||||
@@ -69,13 +99,15 @@ Entry types:
|
||||
- `symlink`: local filesystem symlink;
|
||||
- `other`: unknown or unsupported native entry type.
|
||||
|
||||
`Stat` returns metadata for one logical path.
|
||||
`Stat` returns metadata for one exact logical path. It may report a real filesystem directory, symlink, file, or exact object. It must not synthesize S3-like directory metadata solely because objects exist below a prefix; callers that need prefix existence or destination emptiness must use `HasAny` or `Walk`.
|
||||
|
||||
`Walk` traverses entries below a prefix and calls a callback for each entry. `WalkOptions` should include:
|
||||
|
||||
- whether traversal is recursive;
|
||||
- an optional entry limit for callers that only need to know whether content exists.
|
||||
|
||||
If a callback returns `ErrStopWalk`, traversal stops successfully and `Walk` returns nil. Any other callback error stops traversal and is returned with storage context where practical. If `WalkOptions.Limit` is greater than zero, reaching the limit stops traversal successfully.
|
||||
|
||||
Backends may stream or paginate traversal internally. S3-compatible adapters should not need to load a whole prefix into memory to satisfy traversal.
|
||||
|
||||
Raw traversal is not required to be lexically sorted. A helper that materializes walk results for bundle discovery, tests, or CLI output should sort entries lexically by logical path before returning them.
|
||||
@@ -102,7 +134,8 @@ Both read methods must:
|
||||
|
||||
- content type, when the destination backend can use it;
|
||||
- overwrite permission;
|
||||
- atomic or staged write preference.
|
||||
- atomic or staged write preference;
|
||||
- optional known size for stream writes.
|
||||
|
||||
Backends own staging and atomic behavior where practical:
|
||||
|
||||
@@ -110,6 +143,8 @@ Backends own staging and atomic behavior where practical:
|
||||
- SSH/SFTP backend should use a temporary remote file and rename where available.
|
||||
- S3-compatible backend treats a successful object PUT as publish-on-success and applies content type metadata.
|
||||
|
||||
Remote adapters may buffer or spool `WriteFrom` input when needed to satisfy backend requirements such as content length, multipart upload, or retry behavior. Callers that know the stream size should set `SizeKnown` and `Size`.
|
||||
|
||||
If overwrite is false and the target exists, writes should fail with an already-exists error.
|
||||
|
||||
`WriteFile` and `WriteFrom` should return the written `Entry`, including final path and size where available.
|
||||
|
||||
Reference in New Issue
Block a user