fix: Follows waren über den Client nicht anlegbar
Der Client legt Follows über createRecord mit app.bsky.graph.follow an. Das Lexicon war in der PDS aber nicht registriert, und createRecord validiert per Default — jede Anfrage kam mit 400 lex validation failed: unknown lexicon: app.bsky.graph.follow zurück. Der Follow-Button kann also nie funktioniert haben, auch wenn der Commit, der ihn eingeführt hat, "end-to-end follow / unfollow" heißt. Beim Gegenprüfen des Firehose-Pfads aufgefallen: der Testaufbau scheiterte schon am Anlegen des Follows. Das Lexicon ist jetzt da (subject als DID-String, nicht als strongRef — genau das, was der Client schickt und was follow_subject_did in der AppView liest) und registriert. Live geprüft: anlegen, in der AppView indiziert, löschen, Zeile weg. Dazu ein zweiter Grund, warum das nie auffiel: create_record_with nahm einen Parameter `_validate` entgegen und verwarf ihn. Der eine Aufrufer, der `false` übergab, bekam trotzdem Validierung. Der Parameter wird jetzt tatsächlich mitgeschickt; der Repost-Pfad steht auf `true`, weil genau das bisher schon passiert ist und funktioniert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013HC9HLrUU1LNwkzp8nkDLX
This commit is contained in:
co-authored by
Claude Opus 5
parent
2b695d6892
commit
6fbea4fe6f
@@ -250,7 +250,12 @@ async fn repost_post(
|
||||
});
|
||||
let resp = state
|
||||
.pds
|
||||
.create_record_with(&sess.did, "app.bsky.feed.repost", record, false, &sess.access_jwt)
|
||||
// `true`: `app.bsky.feed.repost` is in the PDS's lexicon registry
|
||||
// and this record passes it (verified against a live PDS). The
|
||||
// `false` that stood here was inert — the flag was dropped before
|
||||
// the request — so validating is what has actually been happening
|
||||
// all along; saying so keeps the behaviour and drops the fiction.
|
||||
.create_record_with(&sess.did, "app.bsky.feed.repost", record, true, &sess.access_jwt)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(serde_json::json!({
|
||||
|
||||
@@ -41,6 +41,10 @@ pub struct CreateRecordReq {
|
||||
pub repo: String,
|
||||
pub collection: String,
|
||||
pub record: serde_json::Value,
|
||||
/// Omitted rather than sent as `null` when the caller has no
|
||||
/// opinion — the PDS's own default (`true`) then applies.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub validate: Option<bool>,
|
||||
}
|
||||
|
||||
/// Strong reference as defined by
|
||||
@@ -184,12 +188,19 @@ impl PdsHttpClient {
|
||||
Ok(r.json().await?)
|
||||
}
|
||||
|
||||
/// `validate` is forwarded to the PDS, which defaults it to `true`.
|
||||
///
|
||||
/// It used to be `_validate` — accepted and silently dropped, so a
|
||||
/// caller asking for `false` still got server-side validation. That
|
||||
/// made no difference in practice (every collection the client writes
|
||||
/// is in the PDS's lexicon registry and passes), but a parameter that
|
||||
/// does nothing is a trap for the next caller who relies on it.
|
||||
pub async fn create_record_with(
|
||||
&self,
|
||||
repo: &str,
|
||||
collection: &str,
|
||||
record: serde_json::Value,
|
||||
_validate: bool,
|
||||
validate: bool,
|
||||
jwt: &str,
|
||||
) -> Result<CreateRecordResp> {
|
||||
let r = self
|
||||
@@ -200,6 +211,7 @@ impl PdsHttpClient {
|
||||
repo: repo.to_string(),
|
||||
collection: collection.to_string(),
|
||||
record,
|
||||
validate: Some(validate),
|
||||
})
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "app.bsky.graph.follow",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "record",
|
||||
"key": "tid",
|
||||
"record": {
|
||||
"type": "object",
|
||||
"required": ["subject", "createdAt"],
|
||||
"properties": {
|
||||
"subject": { "type": "string", "format": "did" },
|
||||
"createdAt": { "type": "datetime" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user