Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ If you set `DATAFOG_API_TOKEN`, send it on every request using:
| `DATAFOG_FGPROF` | `false` | Add `/debug/fgprof` endpoint to the profiling server |
| `DATAFOG_ENABLE_DEMO` | *(unset)* | Enable `/demo*` endpoints |
| `DATAFOG_DEMO_HTML` | `docs/demo.html` | Path to demo HTML |
| `DATAFOG_ENABLE_ADMIN_UI` | *(unset)* | Enable read-only `GET /admin` |
| `DATAFOG_ADMIN_HTML` | `docs/admin.html` | Path to static admin dashboard HTML |

Duration values use Go duration syntax, for example `1s`, `500ms`, `2m`.

Expand All @@ -118,8 +120,10 @@ Base URL defaults to `http://localhost:8080`.
| `POST` | `/v1/decide` | Evaluate an action + findings and get a decision |
| `POST` | `/v1/transform` | Apply requested transform mode(s) |
| `POST` | `/v1/anonymize` | Apply irreversible anonymization |
| `GET` | `/v1/receipts` | List recent decision receipts |
| `GET` | `/v1/receipts/{id}` | Read a decision receipt |
| `GET` | `/v1/events` | List recent decision events |
| `GET` | `/admin` | Read-only operational dashboard (requires DATAFOG_ENABLE_ADMIN_UI) |
| `GET` | `/metrics` | In-process metrics counters |

Optional demo routes (only when demo mode is enabled):
Expand Down Expand Up @@ -192,6 +196,12 @@ curl -X POST http://localhost:8080/v1/transform \
}'
```

### List receipts (admin/read-only)

```sh
curl 'http://localhost:8080/v1/receipts?limit=20&decision=allow'
```

### Fetch a receipt

```sh
Expand Down
35 changes: 31 additions & 4 deletions cmd/datafog-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func main() {
rateLimitRPS := getenvInt("DATAFOG_RATE_LIMIT_RPS", 0)
shutdownTimeout := getenvDuration("DATAFOG_SHUTDOWN_TIMEOUT", 10*time.Second)
enableDemo := getenv("DATAFOG_ENABLE_DEMO", "") != "" || hasFlag("--enable-demo")
enableAdmin := getenvBool("DATAFOG_ENABLE_ADMIN_UI", false) || hasFlag("--enable-admin-ui")
eventsPath := getenv("DATAFOG_EVENTS_PATH", "")
pprofAddr := getenv("DATAFOG_PPROF_ADDR", "")
fgprofEnabled := getenvBool("DATAFOG_FGPROF", false)
Expand Down Expand Up @@ -60,25 +61,48 @@ func main() {
h.SetEventReader(eventReader)
}

var handler http.Handler
var demo *server.DemoHandler
if enableDemo {
// Create a shim gate backed by a local HTTP decision client
client := shim.NewHTTPDecisionClient("http://127.0.0.1"+addr, apiToken)
gate := shim.NewGate(client, shim.WithEventSink(eventSink))

demoHTMLPath := getenv("DATAFOG_DEMO_HTML", "docs/demo.html")
demo, err := server.NewDemoHandler(gate, h, demoHTMLPath)
demo, err = server.NewDemoHandler(gate, h, demoHTMLPath)
if err != nil {
log.Fatalf("init demo: %v", err)
}
defer demo.Cleanup()
}

var admin *server.AdminHandler
if enableAdmin {
adminHTMLPath := getenv("DATAFOG_ADMIN_HTML", "docs/admin.html")
admin, err = server.NewAdminHandler(adminHTMLPath)
if err != nil {
log.Fatalf("init admin UI: %v", err)
}
}

var handler http.Handler
switch {
case demo != nil && admin != nil:
handler = h.HandlerWithDemoAndAdmin(demo, admin)
case demo != nil:
handler = h.HandlerWithDemo(demo)
log.Printf("demo mode enabled — /demo/exec, /demo/write-file, /demo/read-file available")
} else {
case admin != nil:
handler = h.HandlerWithAdmin(admin)
default:
handler = h.Handler()
}

if enableDemo {
log.Printf("demo mode enabled — /demo/exec, /demo/write-file, /demo/read-file available")
}
if enableAdmin {
log.Printf("admin UI enabled — /admin available")
}

var pprofSrv *http.Server
if pprofAddr != "" {
pprofSrv = startProfilingServer(pprofAddr, fgprofEnabled, log.Default())
Expand Down Expand Up @@ -129,6 +153,9 @@ func main() {
log.Printf("forced close failed: %v", closeErr)
}
}
if err := h.Shutdown(ctx); err != nil && !errors.Is(err, context.Canceled) {
log.Printf("application shutdown helper failed: %v", err)
}
if err := <-done; err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Printf("server stopped with error: %v", err)
}
Expand Down
1 change: 1 addition & 0 deletions docs/FRONTEND.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ DataFog API is a backend-first project. There is no React/Vue/Next.js applicatio

- Primary user-facing UI is API-first: clients interact through HTTP endpoints.
- Optional demo assets are static HTML in `docs/demo.html` and rendered by `GET /demo` when demo mode is enabled.
- Optional admin dashboard is static HTML in `docs/admin.html` and rendered by `GET /admin` when admin UI mode is enabled.

## Conventions

Expand Down
Loading
Loading