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
|
let resp = state
|
||||||
.pds
|
.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
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ pub struct CreateRecordReq {
|
|||||||
pub repo: String,
|
pub repo: String,
|
||||||
pub collection: String,
|
pub collection: String,
|
||||||
pub record: serde_json::Value,
|
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
|
/// Strong reference as defined by
|
||||||
@@ -184,12 +188,19 @@ impl PdsHttpClient {
|
|||||||
Ok(r.json().await?)
|
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(
|
pub async fn create_record_with(
|
||||||
&self,
|
&self,
|
||||||
repo: &str,
|
repo: &str,
|
||||||
collection: &str,
|
collection: &str,
|
||||||
record: serde_json::Value,
|
record: serde_json::Value,
|
||||||
_validate: bool,
|
validate: bool,
|
||||||
jwt: &str,
|
jwt: &str,
|
||||||
) -> Result<CreateRecordResp> {
|
) -> Result<CreateRecordResp> {
|
||||||
let r = self
|
let r = self
|
||||||
@@ -200,6 +211,7 @@ impl PdsHttpClient {
|
|||||||
repo: repo.to_string(),
|
repo: repo.to_string(),
|
||||||
collection: collection.to_string(),
|
collection: collection.to_string(),
|
||||||
record,
|
record,
|
||||||
|
validate: Some(validate),
|
||||||
})
|
})
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.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