Skip to content

feat: RFC publication API#9975

Merged
jennifer-richards merged 21 commits intoietf-tools:feat/rpc-apifrom
jennifer-richards:purple-publish
Nov 25, 2025
Merged

feat: RFC publication API#9975
jennifer-richards merged 21 commits intoietf-tools:feat/rpc-apifrom
jennifer-richards:purple-publish

Conversation

@jennifer-richards
Copy link
Copy Markdown
Member

@jennifer-richards jennifer-richards commented Nov 20, 2025

Creating as draft, as there's some additional refactoring to be done.

Summary

Adds two API calls. The first, notify_rfc_published() (/api/purple/rfc/publish/) creates a new RFC Document, using similar procedures to the ietf.sync.rfceditor.update_docs_from_rfc_index() method. The second, upload_rfc_files() (/api/purple/rfc/publish/files/) accepts one or more content files and puts these in place for a specified RFC. The expected publication procedure is to call these in that order. There will be a brief period where the datatracker knows about the RFC but does not yet have its contents, but that is not new behavior compared to the existing sync mechanisms.

notify_rfc_published API

Payload example

{
  "published": "2025-11-20T18:30:12.403Z",
  "draft_name": "draft-QrLqCeSlPaVyKb5",
  "draft_rev": "78",
  "rfc_number": 1,
  "title": "blah blah blah",
  "authors": [
    {
      "titlepage_name": "string",
      "is_editor": true,
      "person": 0,
      "email": "string",
      "affiliation": "string",
      "country": "string"
    }
  ],
  "stream": "string",
  "group": "tools",
  "abstract": "string",
  "pages": 12,
  "words": 2500,
  "formal_languages": [
    "string"
  ],
  "std_level": "string",
  "ad": 0,
  "external_url": "string",
  "obsoletes": [
    0
  ],
  "updates": [
    0
  ],
  "subseries": [
    "std9524"
  ]

The draft_name and draft_rev fields are optional. If present, the RFC is linked as having been published from that draft. If ad, group, or formal_languages are not specified in the API call these are inherited from the draft. Passing null for ad/group or [] for formal_languages will override the draft values with empty ones if needed. All other fields are expected to be supplied in the API call and are not copied from the draft.

upload_rfc_files API

The upload_rfc_files API differs from our existing API in that it expects multipart/form-data encoding of the request to allow chunked file uploads. The code generator we use to generate the Python client for using the API does not seem to handle nested serialization at all with multipart/form-data and has other limitations on the shape of the API it can handle. This is why the file upload API was split from the metadata / RFC creation API call.

Using the generated API client, the upload call looks like

api.upload_rfc_files(rfc=5545, contents=["test.txt"], replace=True)

The rfc parameter is an integer identifying the existing RFC by number. The contents parameter is a list of filenames to be uploaded. The replace option, which defaults to False, specifies whether files already existing for the RFC should prevent the upload from taking place.

The files in contents are uploaded along with their original filenames. Only the extensions are significant and these are used to identify the format of each file. Currently, only .xml, .txt, .txt.pdf, and .html are allowed, and there can only be up to one of each type. The rest of the filename is discarded and files are named like rfcNNNN.{ext} when put in place.

When replace is True, any existing files like rfcNNNN.{ext} for any of the allowed extensions will be unlinked before moving uploaded files into place. My hope is that this will not be used in production except in rare cases. It should not be part of the standard publication workflow except maybe during the early deployment when the old sync mechanism may be running.

@rudimatz
Copy link
Copy Markdown
Contributor

should "draft_rev": "78", be an int, or string?

@jennifer-richards
Copy link
Copy Markdown
Member Author

should "draft_rev": "78", be an int, or string?

It's a string, to match Document.rev for historical reasons. The format is constrained to be exactly two digits, though.

@jennifer-richards jennifer-richards marked this pull request as ready for review November 24, 2025 18:28
Copy link
Copy Markdown
Member

@rjsparks rjsparks left a comment

Choose a reason for hiding this comment

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

Opportunity to fix a bug that the current queue processor has:

log.log("Warning while processing {}: draft {} stream is {} but RFC stream is {}".format(
rfc.name, draft.name, draft.stream, rfc.stream
))
elif draft.stream.slug in ["iab", "irtf", "ise"]:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

needs to get "editorial" too.

@jennifer-richards jennifer-richards merged commit d222c5f into ietf-tools:feat/rpc-api Nov 25, 2025
2 checks passed
@jennifer-richards jennifer-richards deleted the purple-publish branch November 25, 2025 00:19
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 29, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants