WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Conversation

@DaxServer
Copy link
Owner

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Sep 27, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added an OAuth-enabled endpoint to fetch CSRF tokens for Wikibase instances.
    • Introduced support for selecting instances by identifier (wikidata, commons).
  • Refactor

    • Standardized instance handling across app to use identifiers instead of URLs.
    • Default Wikibase selection is now initialized and reset to “wikidata”.
  • Tests

    • Updated test data and assertions to use instance identifiers and the new defaults.

Walkthrough

Adds a POST API route to obtain a Wikibase CSRF token using OAuth credentials, introduces OAuth/CSRF schemas and InstanceId literals, and updates backend clients/services and frontend stores/composables/tests to use typed InstanceId and per-instance OAuth client handling.

Changes

Cohort / File(s) Summary
API: CSRF route
backend/src/api/wikibase/index.ts
New POST /:instanceId/csrf-token accepting { credentials: OAuthCredentials }, calls wikibase.getCsrfToken(instanceId, credentials), returns { token }.
Schemas: InstanceId / OAuth / CSRF
backend/src/api/wikibase/schemas.ts
Added OAuthCredentials and CSRFTokenResponse schemas/types. Changed InstanceId to t.Union(t.Literal('wikidata'), t.Literal('commons')).
Backend: Wikibase clients & service surface
backend/src/services/wikibase-clients.ts, backend/src/services/wikibase.service.ts, backend/src/services/constraint-validation.service.ts
Added per-instance OAuth client caching and getCsrfToken(instanceId, credentials). Switched many instanceId params to InstanceId type across services; updated client lookup signatures.
Backend: MediaWiki API / types
backend/src/services/mediawiki-api.service.ts, backend/src/types/mediawiki-api.ts
Made MediaWikiApiService.config public and made MediaWikiConfig.userAgent required.
Frontend: stores / composables
frontend/src/features/wikibase-schema/stores/schema.store.ts, frontend/src/features/wikibase-schema/composables/useSchemaApi.ts, frontend/src/features/wikibase-schema/composables/useSchemaSelection.ts, frontend/src/features/data-processing/composables/useDataTypeCompatibility.ts
Switched wikibase state/fields to typed InstanceId and initialized default to 'wikidata'; adjusted related composables types/imports.
Tests: frontend/backend tests
frontend/src/.../__tests__/*, backend/tests/api/project/project.wikibase.test.ts
Updated tests/mocks to use 'wikidata' or 'commons' literals for wikibase; small test adjustments and one commented-out assertion block.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant API as API Route (/api/wikibase/:instanceId/csrf-token)
  participant WB as WikibaseClient / Service
  participant OC as OAuth client (per-instance cache)
  participant MW as MediaWiki API

  Client->>API: POST /:instanceId/csrf-token { credentials }
  API->>WB: getCsrfToken(instanceId, credentials)

  alt cached OAuth client exists
    WB->>OC: use cached client (sign requests)
  else no cached client
    WB->>OC: initialize OAuth client with credentials
    note right of OC: store per-instance client
  end

  WB->>MW: GET action=query&meta=tokens&type=csrf (OAuth-signed)
  MW-->>WB: { query: { tokens: { csrftoken } } }
  WB-->>API: { token: csrftoken }
  API-->>Client: 200 { token: "<csrf>" }

  rect rgba(255,230,230,0.6)
  note over WB,API: Error path -> throw / return 4xx-5xx
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description is currently empty and does not provide any summary or context for the changes introduced, which makes it impossible to understand the intent or scope of the work without examining the diff. Please add a concise description summarizing the key changes in this PR, including the new CSRF token endpoint, schema modifications, and service updates, to help reviewers quickly grasp the purpose and impact of the work.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title “feat: fetch CSRF token from MediaWiki Action API” clearly and concisely describes the primary change of adding the ability to retrieve a CSRF token via the MediaWiki Action API, matching the new POST /:instanceId/csrf-token route and associated client and schema updates in the pull request. It follows conventional commit style, avoids unnecessary detail, and provides enough context for a reviewer to understand the main purpose at a glance.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch wikibase-csrf-token

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 172b86f and 02647db.

📒 Files selected for processing (3)
  • backend/src/api/wikibase/index.ts (2 hunks)
  • backend/src/api/wikibase/schemas.ts (1 hunks)
  • backend/src/services/wikibase-clients.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
backend/src/services/wikibase-clients.ts (2)
backend/src/services/mediawiki-api.service.ts (1)
  • MediaWikiApiService (3-80)
backend/src/api/wikibase/schemas.ts (4)
  • OAuthCredentials (4-17)
  • OAuthCredentials (18-18)
  • CSRFTokenResponse (20-26)
  • CSRFTokenResponse (27-27)
backend/src/api/wikibase/index.ts (1)
backend/src/api/wikibase/schemas.ts (2)
  • OAuthCredentials (4-17)
  • OAuthCredentials (18-18)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
backend/src/services/wikibase-clients.ts (1)

13-16: Configured timeout isn’t enforced by MediaWikiApiService.

You set timeout: 30000 but MediaWikiApiService.request() doesn’t use it, so calls won’t actually time out. Either wire it up or drop the field to avoid false guarantees.

Outside-changes snippet (mediawiki-api.service.ts) to enforce timeouts:

// inside request()
const controller = new AbortController()
const id = setTimeout(() => controller.abort(), this.config.timeout ?? 30000)
try {
  const response = await fetch(url.toString(), { ...options, signal: controller.signal })
  ...
} finally {
  clearTimeout(id)
}
backend/src/api/wikibase/schemas.ts (2)

4-17: Tighten credential field validation.

Prevent empty strings to fail fast before hitting the provider.

Apply:

-  consumerKey: t.String({
+  consumerKey: t.String({
+    minLength: 1,
     description: 'Consumer key',
   }),
-  consumerSecret: t.String({
+  consumerSecret: t.String({
+    minLength: 1,
     description: 'Consumer secret',
   }),
-  accessToken: t.String({
+  accessToken: t.String({
+    minLength: 1,
     description: 'Access token',
   }),
-  accessTokenSecret: t.String({
+  accessTokenSecret: t.String({
+    minLength: 1,
     description: 'Access secret',
   }),

48-49: InstanceId literals are clear; consider centralizing mapping.

Since adding a new instance requires edits across schema, endpoints, and clients, consider exporting a single source of truth (e.g., a const INSTANCES = ['wikidata','commons'] as const) and derive both the union and endpoint map from it to avoid drift.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02647db and 63ae16d.

📒 Files selected for processing (17)
  • backend/src/api/wikibase/index.ts (3 hunks)
  • backend/src/api/wikibase/schemas.ts (2 hunks)
  • backend/src/services/constraint-validation.service.ts (4 hunks)
  • backend/src/services/mediawiki-api.service.ts (2 hunks)
  • backend/src/services/wikibase-clients.ts (1 hunks)
  • backend/src/services/wikibase.service.ts (6 hunks)
  • backend/src/types/mediawiki-api.ts (1 hunks)
  • backend/tests/api/project/project.wikibase.test.ts (2 hunks)
  • frontend/src/features/data-processing/composables/useDataTypeCompatibility.ts (0 hunks)
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.ts (18 hunks)
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaCompletenessIntegration.test.ts (3 hunks)
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaCompletenessValidation.test.ts (7 hunks)
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaValidationUI.test.ts (4 hunks)
  • frontend/src/features/wikibase-schema/composables/useSchemaApi.ts (1 hunks)
  • frontend/src/features/wikibase-schema/composables/useSchemaSelection.ts (1 hunks)
  • frontend/src/features/wikibase-schema/stores/__tests__/schema.store.test.ts (1 hunks)
  • frontend/src/features/wikibase-schema/stores/schema.store.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • frontend/src/features/data-processing/composables/useDataTypeCompatibility.ts
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/features/wikibase-schema/composables/tests/useSchemaCompletenessValidation.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/src/api/wikibase/index.ts
🧰 Additional context used
🧬 Code graph analysis (7)
backend/src/services/mediawiki-api.service.ts (1)
backend/src/types/mediawiki-api.ts (1)
  • MediaWikiConfig (12-19)
frontend/src/features/wikibase-schema/stores/schema.store.ts (1)
backend/src/api/wikibase/schemas.ts (2)
  • InstanceId (48-48)
  • InstanceId (49-49)
backend/src/services/wikibase-clients.ts (2)
backend/src/api/wikibase/schemas.ts (6)
  • InstanceId (48-48)
  • InstanceId (49-49)
  • OAuthCredentials (4-17)
  • OAuthCredentials (18-18)
  • CSRFTokenResponse (20-26)
  • CSRFTokenResponse (27-27)
backend/src/services/mediawiki-api.service.ts (1)
  • MediaWikiApiService (3-79)
backend/src/services/constraint-validation.service.ts (1)
backend/src/api/wikibase/schemas.ts (2)
  • InstanceId (48-48)
  • InstanceId (49-49)
backend/tests/api/project/project.wikibase.test.ts (1)
backend/src/api/wikibase/schemas.ts (2)
  • InstanceId (48-48)
  • InstanceId (49-49)
backend/src/services/wikibase.service.ts (2)
backend/src/api/wikibase/schemas.ts (2)
  • InstanceId (48-48)
  • InstanceId (49-49)
backend/src/types/wikibase-schema.ts (4)
  • PropertyId (11-16)
  • PropertyId (17-17)
  • ItemId (3-8)
  • ItemId (9-9)
frontend/src/features/wikibase-schema/composables/useSchemaApi.ts (1)
backend/src/api/wikibase/schemas.ts (2)
  • InstanceId (48-48)
  • InstanceId (49-49)
🔇 Additional comments (19)
frontend/src/features/wikibase-schema/composables/__tests__/useSchemaCompletenessIntegration.test.ts (3)

69-70: InstanceId literal matches store expectation

Using 'wikidata' here keeps the integration test aligned with the new InstanceId-based schema default, so the expectation reads cleanly.


107-107: Consistent literal for incomplete workflow setup

Setting the store to 'wikidata' maintains consistency with the new canonical value while exercising the incomplete-statement path.


153-154: Validation state uses canonical instance

Assigning 'wikidata' before checking the validation state ensures this path reflects the canonical InstanceId and avoids mismatched expectations.

frontend/src/features/wikibase-schema/stores/__tests__/schema.store.test.ts (1)

74-83: Updated default matches InstanceId-backed store state

Confirming the default expectation to 'wikidata' keeps the test aligned with the store’s new InstanceId initializer and reset behavior. Nice catch.

frontend/src/features/wikibase-schema/composables/useSchemaApi.ts (1)

6-10: SchemaRequest now enforces InstanceId

Importing InstanceId and tightening the request type keeps the frontend contract in sync with the backend schema—good defensive typing.

backend/tests/api/project/project.wikibase.test.ts (1)

7-8: Test data aligned with InstanceId literals

Pulling in the new type and asserting 'commons' ensures the PUT path is exercising the expanded InstanceId domain. Looks solid.

Also applies to: 389-392

frontend/src/features/wikibase-schema/composables/useSchemaSelection.ts (1)

50-56: Canonical wikibase preset preserved when starting fresh

Seeding new schemas with 'wikidata' keeps the selection flow consistent with the store’s typed default. All good.

frontend/src/features/wikibase-schema/composables/__tests__/useSchemaValidationUI.test.ts (1)

140-214: Validation tests updated for InstanceId-backed store

Switching the test setup to use the 'wikidata' literal keeps the validation expectations consistent with the new InstanceId handling. No gaps spotted.

backend/src/types/mediawiki-api.ts (1)

14-14: LGTM: Required userAgent aligns with service changes.

This change makes userAgent required, which correctly aligns with the updated MediaWikiApiService that now uses this.config.userAgent directly without fallback. Based on the web search results, MediaWiki APIs typically require a User-Agent header for requests, making this a sensible API contract improvement.

backend/src/services/mediawiki-api.service.ts (2)

4-4: LGTM: Public config access enables per-instance usage.

Making the config public allows external services to access the configuration, which aligns with the PR's objective of supporting per-instance OAuth workflows where different clients may need access to instance-specific configurations.


61-61: LGTM: Direct userAgent usage consistent with type change.

The direct use of this.config.userAgent is now safe since the MediaWikiConfig interface makes userAgent required. This removes the previous implicit fallback and ensures consistent User-Agent headers across requests.

frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.ts (2)

60-60: LGTM: Consistent adoption of 'wikidata' as default instance.

The tests now consistently use 'wikidata' as the standard wikibase value, replacing previous URLs and empty strings. This aligns with the new InstanceId type system and provides better type safety and consistency across the application.

Also applies to: 205-205, 211-211, 316-316, 337-337, 372-372, 381-381, 421-421, 447-447, 562-562, 579-579, 601-601, 618-618, 656-656, 683-683, 710-710, 761-761


232-234: Good use of TypeScript error directives for invalid test cases.

The @ts-expect-error annotations appropriately mark invalid wikibase assignments for testing purposes, ensuring the type system catches invalid usage while allowing explicit testing of error conditions.

Also applies to: 543-545

frontend/src/features/wikibase-schema/stores/schema.store.ts (1)

11-11: LGTM: Proper adoption of InstanceId type with sensible defaults.

The changes correctly:

  • Import the InstanceId type from the backend schema definitions
  • Initialize the wikibase ref with the 'wikidata' literal that matches the union type
  • Reset to the same default value

This provides type safety while maintaining backwards compatibility with sensible defaults. Based on learnings from the search results, Wikidata is the most commonly used Wikibase instance, making it an appropriate default choice.

Also applies to: 26-26, 499-499

backend/src/services/constraint-validation.service.ts (1)

1-1: LGTM: Consistent InstanceId adoption across validation methods.

The changes properly:

  • Import the InstanceId type from the centralized schema definitions
  • Update all public method signatures to use InstanceId for type safety
  • Maintain existing caching and error handling logic

This ensures consistent typing across the Wikibase service layer and provides better type safety for instance-specific constraint validation operations.

Also applies to: 19-19, 398-398, 488-488

backend/src/services/wikibase-clients.ts (2)

6-9: SSRF risk addressed — endpoints are now server-controlled.

Hardcoding per-instance API endpoints removes the earlier SSRF vector. Good fix.


3-3: Incorrect suggestion: import { OAuth } from 'oauth' isn’t valid
The oauth package’s typings use CommonJS exports (no named OAuth export), so import { OAuth } from 'oauth' will fail even with esModuleInterop enabled. Continue using the default import (or the import OAuth = require('oauth') form) and reference the class directly (e.g. new OAuth(...)) rather than switching to a non‐existent named export.

Likely an incorrect or invalid review comment.

backend/src/api/wikibase/schemas.ts (1)

20-27: CSRFTokenResponse shape looks correct.

Matches MediaWiki’s meta=tokens&type=csrf response.

backend/src/services/wikibase.service.ts (1)

35-36: Typed InstanceId adoption verified — no remaining raw string callers.
Ran RG search across codebase; all calls to fetchAllProperties, searchProperties, getProperty, searchItems, and getItem now use typed instanceId, with no raw 'wikidata' or 'commons' arguments.

Comment on lines +24 to +25
private credentials: Partial<Record<InstanceId, OAuthCredentials>> = {}
private authenticatedClients: Partial<Record<InstanceId, OAuth.OAuth>> = {}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Do not retain OAuth credentials in memory.

this.credentials stores secrets beyond the request lifetime and gets overwritten per instance; unnecessary and a privacy/compliance risk. Remove it; pass creds per call only (you already do).

Apply:

-  private credentials: Partial<Record<InstanceId, OAuthCredentials>> = {}
   private authenticatedClients: Partial<Record<InstanceId, OAuth.OAuth>> = {}
...
-      this.credentials[instanceId] = credentials

Also applies to: 38-38

Comment on lines +39 to +41
this.authenticatedClients[instanceId] = new OAuth.OAuth(
this.endpoints[instanceId],
this.endpoints[instanceId],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use MediaWiki OAuth1 endpoints, not the Action API URL.

OAuth.OAuth’s first two args must be the request/access token endpoints. Using /w/api.php is wrong (works only by accident because you’re not calling token flows). Also set a request timeout on the OAuth client.

Apply:

-      this.authenticatedClients[instanceId] = new OAuth.OAuth(
-        this.endpoints[instanceId],
-        this.endpoints[instanceId],
+      const base = new URL(this.endpoints[instanceId]).origin
+      const requestTokenUrl = `${base}/w/index.php?title=Special:OAuth/initiate`
+      const accessTokenUrl  = `${base}/w/index.php?title=Special:OAuth/token`
+      const oa = new OAuth.OAuth(
+        requestTokenUrl,
+        accessTokenUrl,
         credentials.consumerKey,
         credentials.consumerSecret,
         '1.0',
         null,
         'HMAC-SHA1',
         undefined,
         {
           'User-Agent': client.config.userAgent,
         },
       )
+      // Ensure outbound calls don’t hang indefinitely
+      oa.setClientOptions?.({ timeout: 30000 })
+      this.authenticatedClients[instanceId] = oa

Based on learnings.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.authenticatedClients[instanceId] = new OAuth.OAuth(
this.endpoints[instanceId],
this.endpoints[instanceId],
const base = new URL(this.endpoints[instanceId]).origin
const requestTokenUrl = `${base}/w/index.php?title=Special:OAuth/initiate`
const accessTokenUrl = `${base}/w/index.php?title=Special:OAuth/token`
const oa = new OAuth.OAuth(
requestTokenUrl,
accessTokenUrl,
credentials.consumerKey,
credentials.consumerSecret,
'1.0',
null,
'HMAC-SHA1',
undefined,
{
'User-Agent': client.config.userAgent,
},
)
// Ensure outbound calls don’t hang indefinitely
oa.setClientOptions?.({ timeout: 30000 })
this.authenticatedClients[instanceId] = oa

Comment on lines +56 to 83
async getCsrfToken(
instanceId: InstanceId,
credentials: OAuthCredentials,
): Promise<CSRFTokenResponse> {
const authService = this.getAuthenticatedClient(instanceId, credentials)

return new Promise((resolve, reject) => {
authService.get(
this.endpoints[instanceId] +
'?' +
new URLSearchParams({
action: 'query',
meta: 'tokens',
format: 'json',
}).toString(),
credentials.accessToken,
credentials.accessTokenSecret,
(err, data) => {
if (err) {
console.error(err)
reject(err)
return
}
resolve(JSON.parse(data as string) as CSRFTokenResponse)
},
)
})
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Be explicit with type=csrf and harden JSON parsing.

Add type=csrf to the query to avoid provider defaults changing; also guard JSON.parse errors and validate shape.

Apply:

       authService.get(
         this.endpoints[instanceId] +
           '?' +
           new URLSearchParams({
             action: 'query',
             meta: 'tokens',
+            type: 'csrf',
             format: 'json',
           }).toString(),
         credentials.accessToken,
         credentials.accessTokenSecret,
         (err, data) => {
           if (err) {
             console.error(err)
             reject(err)
             return
           }
-          resolve(JSON.parse(data as string) as CSRFTokenResponse)
+          try {
+            const parsed = JSON.parse(data as string) as CSRFTokenResponse
+            if (!parsed?.query?.tokens?.csrftoken) {
+              return reject(new Error('Missing csrftoken in response'))
+            }
+            resolve(parsed)
+          } catch (e) {
+            reject(e)
+          }
         },
       )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async getCsrfToken(
instanceId: InstanceId,
credentials: OAuthCredentials,
): Promise<CSRFTokenResponse> {
const authService = this.getAuthenticatedClient(instanceId, credentials)
return new Promise((resolve, reject) => {
authService.get(
this.endpoints[instanceId] +
'?' +
new URLSearchParams({
action: 'query',
meta: 'tokens',
format: 'json',
}).toString(),
credentials.accessToken,
credentials.accessTokenSecret,
(err, data) => {
if (err) {
console.error(err)
reject(err)
return
}
resolve(JSON.parse(data as string) as CSRFTokenResponse)
},
)
})
}
async getCsrfToken(
instanceId: InstanceId,
credentials: OAuthCredentials,
): Promise<CSRFTokenResponse> {
const authService = this.getAuthenticatedClient(instanceId, credentials)
return new Promise((resolve, reject) => {
authService.get(
this.endpoints[instanceId] +
'?' +
new URLSearchParams({
action: 'query',
meta: 'tokens',
type: 'csrf',
format: 'json',
}).toString(),
credentials.accessToken,
credentials.accessTokenSecret,
(err, data) => {
if (err) {
console.error(err)
reject(err)
return
}
try {
const parsed = JSON.parse(data as string) as CSRFTokenResponse
if (!parsed?.query?.tokens?.csrftoken) {
return reject(new Error('Missing csrftoken in response'))
}
resolve(parsed)
} catch (e) {
reject(e)
}
},
)
})
}
🤖 Prompt for AI Agents
In backend/src/services/wikibase-clients.ts around lines 56 to 83, the query
that requests tokens should explicitly include type=csrf and the JSON parsing
must be hardened: add type: 'csrf' to the URLSearchParams; wrap JSON.parse in a
try/catch and reject with a descriptive error if parsing fails; after parsing,
validate the parsed object has the expected shape (e.g., top-level
query.tokens.csrf or whatever CSRFTokenResponse requires) and reject if
validation fails; keep returning the parsed CSRFTokenResponse on success.

@DaxServer DaxServer merged commit 237827c into main Sep 28, 2025
6 checks passed
@DaxServer DaxServer deleted the wikibase-csrf-token branch September 28, 2025 09:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants