| 1 |
|
package main |
| 2 |
|
|
| 3 |
|
import ( |
| 4 |
|
"context" |
| 5 |
|
|
| 6 |
|
"github.com/vaughan0/go-ini" |
| 7 |
|
|
| 8 |
|
"sourcecraft.dev/bigbes/sr-ht-dolt/browse" |
| 9 |
|
"sourcecraft.dev/bigbes/sr-ht-dolt/graph" |
| 10 |
|
"sourcecraft.dev/bigbes/sr-ht-dolt/web" |
| 11 |
|
) |
| 12 |
|
|
| 13 |
|
// queryRoute is where the GraphQL schema answers. It is core-go's own path, |
| 14 |
|
// because that is where every SourceHut client — hut, api.sr.ht, meta's |
| 15 |
|
// personal-token page — already looks. The file beside it is served by |
| 16 |
|
// ecore's apimeta, at apimeta.Path. |
| 17 |
|
const queryRoute = "/query" |
| 18 |
|
|
| 19 |
|
// repoScopeName is the one grant this service defines, spelled as meta.sr.ht |
| 20 |
|
// expects it: the part after the service name in authn.RepoScope |
| 21 |
|
// ("dolt.sr.ht/repos"). meta prefixes the service name itself. The two |
| 22 |
|
// spellings are the same fact written twice, so a test asserts them equal — |
| 23 |
|
// a drift would let a user mint a token meta calls valid and this service does |
| 24 |
|
// not honour. |
| 25 |
|
const repoScopeName = "repos" |
| 26 |
|
|
| 27 |
|
// graphBrowseOpener satisfies graph.BrowseOpener over browse.Open, as |
| 28 |
|
// mcpBrowseOpener does for the MCP surface and web.BrowseAdapter for the pages: |
| 29 |
|
// one *browse.DB answers all three method sets, and each package declares the |
| 30 |
|
// seam it consumes rather than importing another's. |
| 31 |
|
type graphBrowseOpener struct{} |
| 32 |
|
|
| 33 |
|
var _ graph.BrowseOpener = graphBrowseOpener{} |
| 34 |
|
|
| 35 |
0 |
func (graphBrowseOpener) Open(ctx context.Context, diskPath string) (graph.BrowseSession, error) { |
| 36 |
0 |
dbh, err := browse.Open(ctx, diskPath) |
| 37 |
0 |
if err != nil { |
| 38 |
0 |
return nil, err |
| 39 |
0 |
} |
| 40 |
0 |
return dbh, nil |
| 41 |
|
} |
| 42 |
|
|
| 43 |
|
// newGraphServer assembles /query over the seams the daemon already has: the |
| 44 |
|
// same request-scoped metadata adapter the web pages and the MCP tools read |
| 45 |
|
// through, and the same bare-store reader. |
| 46 |
|
// |
| 47 |
|
// It shares /mcp's credential plane, validator included, so an instance that |
| 48 |
|
// runs no tokens.sr.ht refuses a working token on both surfaces and accepts |
| 49 |
|
// meta PATs and anonymous callers on both. Its failures are fatal for the same |
| 50 |
|
// reason /mcp's are: a surface that answers every query "could not be read" |
| 51 |
|
// because a seam was never wired is a daemon that starts and does not work. |
| 52 |
7 |
func newGraphServer(conf ini.File) (*graph.Server, error) { |
| 53 |
7 |
validator, err := newBearerValidator(conf) |
| 54 |
7 |
if err != nil { |
| 55 |
0 |
return nil, err |
| 56 |
0 |
} |
| 57 |
7 |
return graph.New(graph.Options{ |
| 58 |
7 |
Repos: web.DBAdapter{}, |
| 59 |
7 |
Browse: graphBrowseOpener{}, |
| 60 |
7 |
Validator: validator, |
| 61 |
7 |
}) |
| 62 |
|
} |