diff --git a/docs/events/login_body_buttons_before.txt b/docs/events/login_body_buttons_before.txt
new file mode 100644
index 0000000..253665a
--- /dev/null
+++ b/docs/events/login_body_buttons_before.txt
@@ -0,0 +1,59 @@
+TITLE
+=====
+[RFC] New template event login_body_buttons_before
+
+BODY
+====
+login_body.html has no tags anywhere in it. The PHP side
+of the login form already has a usable hook: core.login_box_before
+fires at the very start of login_box() in includes/functions.php,
+before credentials are checked, and exposes a settable $err string
+that aborts the login attempt when non-empty. What's missing is a
+place in the template to actually render a widget into the form, so
+an extension can only reject a bad submission server-side, never show
+anything to the user client-side.
+
+Concretely: mosparo/phpbbintegration (a CAPTCHA-alternative extension)
+already protects the registration and posting forms, both of which do
+have template events to render its widget into. The login form is the
+one place login_box_before exists but the widget has nowhere to go.
+
+This is the same gap and the same proposed name as an identical request
+from a separate honeypot-style anti-spam extension, so this should be
+treated as one shared request rather than two competing ones if it's
+ever filed against phpBB.
+
+PROPOSED EVENT (template)
+--------------------------
+Name: login_body_buttons_before
+File: styles/prosilver/template/login_body.html
+Location: immediately after the form token, immediately before the
+submit-button block.
+
+Current markup at that point:
+
+ {S_LOGIN_REDIRECT}
+ {S_FORM_TOKEN_LOGIN}
+
+
+TESTING
+-------
+Manually verified against the phpBB 3.3.17 branch (checked
+styles/prosilver/template/login_body.html and the login_box_before
+trigger_event() call in includes/functions.php directly) that no
+ tag exists anywhere in the login template, and that
+core.login_box_before already exposes a settable $err before the
+credential check runs.
diff --git a/docs/events/ucp_remind_request_before.txt b/docs/events/ucp_remind_request_before.txt
new file mode 100644
index 0000000..37118e0
--- /dev/null
+++ b/docs/events/ucp_remind_request_before.txt
@@ -0,0 +1,87 @@
+TITLE
+=====
+[RFC] New PHP event core.ucp_remind_request_before
+
+BODY
+====
+phpbb\ucp\controller\reset_password::request() (the "forgot password,
+enter your email" step) only has core.ucp_remind_modify_select_sql,
+which lets an extension tweak the SQL query used to look up the user.
+It has no variable an extension can use to reject the submission
+outright, and no place before the form-key check to hook in.
+
+Concretely: mosparo/phpbbintegration already protects registration and
+posting the same way, an event fires, the extension checks a submitted
+token against the mosparo API, and on failure it rejects the request
+before any further processing happens. This method has nowhere to do
+that.
+
+This request pairs with docs/events/ucp_reset_password_verify_before.txt
+(the second step of the same flow) and
+docs/events/ucp_reset_password_widget_before.txt (the shared template
+event both steps render through).
+
+PROPOSED EVENT (PHP)
+---------------------
+Name: core.ucp_remind_request_before
+File: phpbb/ucp/controller/reset_password.php, function request()
+Location: immediately after the form-key check, before the existing
+empty($email) check. Every other failure case in this method already
+returns via $this->helper->message('LANG_KEY'), so a settable $error
+language key fits the method's existing convention exactly, no new
+error-display mechanism needed.
+
+Current markup at that point:
+
+ if ($submit)
+ {
+ if (!check_form_key('ucp_reset_password'))
+ {
+ throw new http_exception(Response::HTTP_UNAUTHORIZED, 'FORM_INVALID');
+ }
+
+ if (empty($email))
+ {
+ return $this->helper->message('NO_EMAIL_USER');
+ }
+
+Proposed insertion:
+
+ if ($submit)
+ {
+ if (!check_form_key('ucp_reset_password'))
+ {
+ throw new http_exception(Response::HTTP_UNAUTHORIZED, 'FORM_INVALID');
+ }
+
+ $error = '';
+
+ /**
+ * Verify a password reset request before it is processed
+ *
+ * @event core.ucp_remind_request_before
+ * @var string email User's email from the form
+ * @var string username User's username from the form
+ * @var string error Language key to abort with, empty string if the request is valid
+ * @since to be filled in by the phpBB dev team at merge time
+ */
+ $vars = array('email', 'username', 'error');
+ extract($this->dispatcher->trigger_event('core.ucp_remind_request_before', compact($vars)));
+
+ if ($error)
+ {
+ return $this->helper->message($error);
+ }
+
+ if (empty($email))
+ {
+ return $this->helper->message('NO_EMAIL_USER');
+ }
+
+TESTING
+-------
+Manually verified against the phpBB 3.3.17 branch (checked
+phpbb/ucp/controller/reset_password.php directly) that
+core.ucp_remind_modify_select_sql is a SQL-array-only hook with no
+error/rejection variable, and that request() has no other event before
+the SQL query is built.
diff --git a/docs/events/ucp_reset_password_verify_before.txt b/docs/events/ucp_reset_password_verify_before.txt
new file mode 100644
index 0000000..dea40b0
--- /dev/null
+++ b/docs/events/ucp_reset_password_verify_before.txt
@@ -0,0 +1,72 @@
+TITLE
+=====
+[RFC] New PHP event core.ucp_reset_password_verify_before
+
+BODY
+====
+phpbb\ucp\controller\reset_password::reset() (the "enter your new
+password" step, reached from the emailed link) only has
+core.ucp_reset_password_modify_select_sql, which lets an extension
+tweak the SQL query used to look up the token. It has no variable an
+extension can use to reject the submission.
+
+Unlike the request() step, this method already builds an $errors array
+(from validate_data() on the new password fields) that the template
+renders via PASSWORD_RESET_ERRORS. A new event that can append to that
+same $errors array needs no template change and no new error-display
+mechanism, it plugs directly into the existing gate.
+
+This request pairs with docs/events/ucp_remind_request_before.txt (the
+first step of the same flow) and
+docs/events/ucp_reset_password_widget_before.txt (the shared template
+event both steps render through).
+
+PROPOSED EVENT (PHP)
+---------------------
+Name: core.ucp_reset_password_verify_before
+File: phpbb/ucp/controller/reset_password.php, function reset()
+Location: immediately after the new_password/password_confirm
+validation, immediately before the existing "if (empty($errors))" gate
+that saves the new password.
+
+Current markup at that point:
+
+ $errors = array_merge($errors, validate_data($data, $check_data));
+ if (strcmp($data['new_password'], $data['password_confirm']) !== 0)
+ {
+ $errors[] = $data['password_confirm'] ? 'NEW_PASSWORD_ERROR' : 'NEW_PASSWORD_CONFIRM_EMPTY';
+ }
+ if (empty($errors))
+ {
+
+Proposed insertion:
+
+ $errors = array_merge($errors, validate_data($data, $check_data));
+ if (strcmp($data['new_password'], $data['password_confirm']) !== 0)
+ {
+ $errors[] = $data['password_confirm'] ? 'NEW_PASSWORD_ERROR' : 'NEW_PASSWORD_CONFIRM_EMPTY';
+ }
+
+ /**
+ * Verify a password reset submission before the new password is saved
+ *
+ * @event core.ucp_reset_password_verify_before
+ * @var array user_row The user row the password is being reset for
+ * @var array data Submitted new_password/password_confirm
+ * @var array errors Array of language keys, append to reject the submission
+ * @since to be filled in by the phpBB dev team at merge time
+ */
+ $vars = array('user_row', 'data', 'errors');
+ extract($this->dispatcher->trigger_event('core.ucp_reset_password_verify_before', compact($vars)));
+
+ if (empty($errors))
+ {
+
+TESTING
+-------
+Manually verified against the phpBB 3.3.17 branch (checked
+phpbb/ucp/controller/reset_password.php directly) that
+core.ucp_reset_password_modify_select_sql is a SQL-array-only hook with
+no error/rejection variable, and that reset() already has a working
+$errors array and PASSWORD_RESET_ERRORS template output this event can
+plug into without any template change.
diff --git a/docs/events/ucp_reset_password_widget_before.txt b/docs/events/ucp_reset_password_widget_before.txt
new file mode 100644
index 0000000..240e497
--- /dev/null
+++ b/docs/events/ucp_reset_password_widget_before.txt
@@ -0,0 +1,54 @@
+TITLE
+=====
+[RFC] New template event ucp_reset_password_widget_before
+
+BODY
+====
+ucp_reset_password.html has no {% EVENT %} tags anywhere in it. Both
+steps of the password-reset flow (the "enter your email" request step
+and the "enter your new password" reset step) render through this one
+file, toggled by the S_IS_PASSWORD_RESET conditional, so a single event
+placed outside that conditional and before the shared submit button
+covers both steps at once, no need for two separate template events.
+
+Concretely: mosparo/phpbbintegration already renders its widget into
+the registration and posting forms through template events. This file
+has nowhere for it to go on either step of password reset.
+
+This request pairs with docs/events/ucp_remind_request_before.txt and
+docs/events/ucp_reset_password_verify_before.txt, the PHP-side
+verification events for the request and reset steps respectively.
+
+PROPOSED EVENT (template)
+--------------------------
+Name: ucp_reset_password_widget_before
+File: styles/prosilver/template/ucp_reset_password.html
+Location: immediately after the closing {% endif %} of the
+S_IS_PASSWORD_RESET conditional, immediately before the shared
+submit-button block.
+
+Current markup at that point:
+
+ {% endif %}
+
+
+TESTING
+-------
+Manually verified against the phpBB 3.3.17 branch (checked
+styles/prosilver/template/ucp_reset_password.html and
+phpbb/ucp/controller/reset_password.php directly) that both request()
+and reset() render this same template file, that no {% EVENT %} tag
+exists anywhere in it, and that ucp_resend.html (a separate template)
+is the resend-activation-email flow, unrelated to password reset.