I'm creating an "HR" application which essentially just synchronizes information from an external service and stores the management hierarchy of our organization in Phabricator. I don't really need to create any tables for this, I can just store edges which define the relationships between a manager and their reports. This probably subverts the way that edges are "supposed" to be used. Eg, I know I can just write edges into the people database instead, and that would actually represent the data graph correctly. However, we try to avoid writing custom application code that writes to upstream databases wherever we can, preferring our own third party storage databases instead. This makes clarifying what is upstream managed data and internally managed data much easier.
In any case, I don't seem to be able to just create a schema spec that holds edges and nothing else, unless I'm missing something?
There's no natural way to do this.
You can copy/paste the content of buildEdgeSchemata() into the buildSchemata() method of a SchemaSpec, but then your edge table schema won't pick up upstream updates. This is probably reasonable for v0 though and by the time it's a problem you'll probably have added a real object?
You can build some kind of fake object which implements getApplicationName() in a trivial way and pass that to buildEdgeSchemata($synthetic_object), but I think bin/storage status will get upset that your fake object doesn't have a table. Just copy/pasting a frozen definition of an edge table is probably cleaner.
There is an edge schema change on the horizon somewhere: I plan to drop the data table and the dataID column. I believe it has no readers or writers after reviewers were moved back to a dedicated table in connection with T10967. But this probably won't be much different for you whether you freeze the schema spec or not, and likely only a few minutes of work in either case. There's also no rush on this.
Finally, you can implement some trivial real object with a real table, e.g. whatever you anticipate to be the thing you're most likely to need, even if you never do.
Actually, I think you can't write or query edges without a real object, since EdgeQuery and EdgeEditor both build a real object to figure out which database they should look at.
If your new edge type is just between users (e.g., UserHasDottedLineReportToUser or whatever), you can just create a new EdgeType. It will read/write to the phabricator_user.edge database, but that's fine/safe/expected/supported. This is the approach I'd expect to at least start with if I were implementing an org chart sort of app as an extension.