Skip to content

Commit aab415c

Browse files
authored
Merge pull request #15 from MB3R-Lab/feat/mvp-bootstrap-contract-pr1
[MVP][PR1] Bootstrap scaffold + canonical schema contract foundation
2 parents 6627a08 + e19cf82 commit aab415c

36 files changed

Lines changed: 3014 additions & 1 deletion

.github/workflows/ci.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
checks:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v4
15+
16+
- name: Setup Go
17+
uses: actions/setup-go@v5
18+
with:
19+
go-version-file: go.mod
20+
21+
- name: Lint
22+
run: make lint
23+
24+
- name: Test
25+
run: make test
26+
27+
- name: Build
28+
run: make build
29+

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
bin/
2+
out/
3+
dist/
4+
*.exe
5+
*.test
6+
*.out
7+
coverage.txt
8+
.DS_Store
9+
.idea/
10+
.vscode/
11+

CONTRIBUTING.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Contributing
2+
3+
Thanks for contributing to Bering.
4+
5+
## Development
6+
7+
1. Install Go 1.23+.
8+
2. Run `make lint test build` before opening a PR.
9+
3. Keep model contract compatibility intact:
10+
- `metadata.schema.name = io.mb3r.bering.model`
11+
- `metadata.schema.version = 1.0.0`
12+
- `metadata.schema.uri = https://schemas.mb3r.dev/bering/model/v1.0.0/model.schema.json`
13+
- `metadata.schema.digest = sha256:7dc733936a9d3f94ab92f46a30d4c8d0f5c05d60670c4247786c59a3fe7630f7`
14+
15+
## PR checklist
16+
17+
- [ ] New behavior is covered by tests.
18+
- [ ] `bering discover` output stays deterministic.
19+
- [ ] `bering validate` passes for examples.
20+
- [ ] Docs updated if flags, formats, or heuristics changed.
21+

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
MIT License
2+
3+
Copyright (c) 2026 MB3R-Lab
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+

Makefile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
SHELL := /bin/sh
2+
3+
GO ?= go
4+
IMAGE ?= bering:dev
5+
6+
.PHONY: help lint test build run-checks docker-build clean
7+
8+
help:
9+
@echo "Targets:"
10+
@echo " lint Run gofmt and go vet"
11+
@echo " test Run unit and integration tests"
12+
@echo " build Build bering binary"
13+
@echo " run-checks Run lint + test + build"
14+
@echo " docker-build Build CLI image"
15+
@echo " clean Remove generated binaries"
16+
17+
lint:
18+
@fmt_out="$$(gofmt -l .)"; \
19+
if [ -n "$$fmt_out" ]; then \
20+
echo "gofmt required for:"; \
21+
echo "$$fmt_out"; \
22+
exit 1; \
23+
fi
24+
$(GO) vet ./...
25+
26+
test:
27+
$(GO) test ./...
28+
29+
build:
30+
mkdir -p bin
31+
$(GO) build -o bin/bering ./cmd/bering
32+
33+
run-checks: lint test build
34+
35+
docker-build:
36+
docker build -f build/Dockerfile -t $(IMAGE) .
37+
38+
clean:
39+
rm -rf bin out dist
40+

README.md

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,99 @@
11
# Bering
2-
First Model Discovery tool
2+
3+
Bering is the upstream model discovery tool for Sheaft.
4+
It consumes trace artifacts and produces canonical `bering-model.json` in
5+
`BeringResilienceModel` v1.0.0 contract format.
6+
7+
## Contract (strict)
8+
9+
Bering pins `metadata.schema` exactly:
10+
11+
- `name`: `io.mb3r.bering.model`
12+
- `version`: `1.0.0`
13+
- `uri`: `https://schemas.mb3r.dev/bering/model/v1.0.0/model.schema.json`
14+
- `digest`: `sha256:7dc733936a9d3f94ab92f46a30d4c8d0f5c05d60670c4247786c59a3fe7630f7`
15+
16+
Any mismatch fails validation.
17+
18+
## Repository layout
19+
20+
```text
21+
cmd/bering CLI entrypoint
22+
internal/app command wiring
23+
internal/connectors/traces trace file/dir loading and normalization
24+
internal/discovery model inference from normalized spans
25+
internal/model model structs, semantic checks, canonical IO
26+
internal/schema pinned contract constants + JSON Schema validation
27+
internal/jsoncanon deterministic recursive JSON encoder
28+
api/schema canonical public schema
29+
configs sample configs (replicas override)
30+
examples trace fixtures + expected output artifacts
31+
docs format, heuristic, and MVP limits
32+
scripts/ci CI helper scripts
33+
```
34+
35+
## Commands
36+
37+
```bash
38+
bering discover --input <trace-file|dir> [--out bering-model.json] [--replicas replicas.yaml|json] [--discovered-at RFC3339]
39+
bering validate --input <bering-model.json>
40+
```
41+
42+
## Quickstart
43+
44+
### 1) Discover from traces
45+
46+
```bash
47+
go run ./cmd/bering discover \
48+
--input examples/traces/normalized.sample.json \
49+
--out examples/outputs/bering-model.normalized.sample.json \
50+
--discovered-at 2026-03-03T00:00:00Z
51+
```
52+
53+
### 2) Validate artifact
54+
55+
```bash
56+
go run ./cmd/bering validate \
57+
--input examples/outputs/bering-model.normalized.sample.json
58+
```
59+
60+
### 3) Run Sheaft manually on generated model
61+
62+
```bash
63+
# from sibling Sheaft repository
64+
go run ./cmd/sheaft run \
65+
--model ../Bering/examples/outputs/bering-model.normalized.sample.json \
66+
--policy configs/gate.policy.example.yaml \
67+
--out-dir out \
68+
--seed 42
69+
```
70+
71+
## Deterministic output
72+
73+
Bering output is deterministic for identical inputs and flags:
74+
75+
- services sorted by `id`
76+
- edges sorted by `(from,to,kind,blocking)`
77+
- endpoints sorted by `id`
78+
- stable IDs for services/edges/endpoints
79+
- canonical JSON writer with recursive object-key ordering (future-safe for map fields)
80+
- optional `--discovered-at` for reproducible timestamps
81+
82+
## Supported trace formats (MVP)
83+
84+
- Normalized JSON: `{"spans": [...]}` payload with canonical span fields.
85+
- Raw OTel JSON: `resourceSpans/scopeSpans/spans` payload.
86+
87+
Details: [docs/trace-input-format.md](docs/trace-input-format.md)
88+
89+
## CI and local checks
90+
91+
```bash
92+
make lint
93+
make test
94+
make build
95+
```
96+
97+
## License
98+
99+
MIT (see [LICENSE](LICENSE)).

api/schema/model.schema.json

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.mb3r.dev/bering/model/v1.0.0/model.schema.json",
4+
"title": "BeringResilienceModel",
5+
"type": "object",
6+
"required": [
7+
"services",
8+
"edges",
9+
"endpoints",
10+
"metadata"
11+
],
12+
"properties": {
13+
"services": {
14+
"type": "array",
15+
"items": {
16+
"type": "object",
17+
"required": [
18+
"id",
19+
"name",
20+
"replicas"
21+
],
22+
"properties": {
23+
"id": {
24+
"type": "string"
25+
},
26+
"name": {
27+
"type": "string"
28+
},
29+
"replicas": {
30+
"type": "integer",
31+
"minimum": 0
32+
}
33+
}
34+
}
35+
},
36+
"edges": {
37+
"type": "array",
38+
"items": {
39+
"type": "object",
40+
"required": [
41+
"from",
42+
"to",
43+
"kind",
44+
"blocking"
45+
],
46+
"properties": {
47+
"from": {
48+
"type": "string"
49+
},
50+
"to": {
51+
"type": "string"
52+
},
53+
"kind": {
54+
"type": "string",
55+
"enum": [
56+
"sync",
57+
"async"
58+
]
59+
},
60+
"blocking": {
61+
"type": "boolean"
62+
}
63+
}
64+
}
65+
},
66+
"endpoints": {
67+
"type": "array",
68+
"items": {
69+
"type": "object",
70+
"required": [
71+
"id",
72+
"entry_service",
73+
"success_predicate_ref"
74+
],
75+
"properties": {
76+
"id": {
77+
"type": "string"
78+
},
79+
"entry_service": {
80+
"type": "string"
81+
},
82+
"success_predicate_ref": {
83+
"type": "string"
84+
}
85+
}
86+
}
87+
},
88+
"metadata": {
89+
"type": "object",
90+
"required": [
91+
"source_type",
92+
"source_ref",
93+
"discovered_at",
94+
"confidence",
95+
"schema"
96+
],
97+
"properties": {
98+
"source_type": {
99+
"type": "string"
100+
},
101+
"source_ref": {
102+
"type": "string"
103+
},
104+
"discovered_at": {
105+
"type": "string",
106+
"format": "date-time"
107+
},
108+
"confidence": {
109+
"type": "number",
110+
"minimum": 0,
111+
"maximum": 1
112+
},
113+
"schema": {
114+
"type": "object",
115+
"required": [
116+
"name",
117+
"version",
118+
"uri",
119+
"digest"
120+
],
121+
"properties": {
122+
"name": {
123+
"type": "string"
124+
},
125+
"version": {
126+
"type": "string"
127+
},
128+
"uri": {
129+
"type": "string"
130+
},
131+
"digest": {
132+
"type": "string"
133+
}
134+
}
135+
}
136+
}
137+
}
138+
}
139+
}
140+

build/Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM golang:1.23 AS builder
2+
WORKDIR /src
3+
4+
COPY go.mod go.sum* ./
5+
RUN go mod download
6+
7+
COPY . .
8+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/bering ./cmd/bering
9+
10+
FROM gcr.io/distroless/static-debian12
11+
COPY --from=builder /out/bering /usr/local/bin/bering
12+
ENTRYPOINT ["/usr/local/bin/bering"]
13+

cmd/bering/main.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
import (
4+
"os"
5+
6+
"github.com/MB3R-Lab/Bering/internal/app"
7+
)
8+
9+
func main() {
10+
runner := app.NewRunner(os.Stdout, os.Stderr)
11+
os.Exit(runner.Run(os.Args[1:]))
12+
}

0 commit comments

Comments
 (0)