Block attributes live in the comment delimiter

A block is stored in post_content as an HTML comment wrapping markup, and its attributes are JSON inside that comment — which is why the post is still readable if every plugin is removed.

<!-- wp:turkerdev/notice {"tone":"warning","dismissible":true} -->
<div class="wp-block-turkerdev-notice is-warning">
  <p>Back up before running this.</p>
</div>
<!-- /wp:turkerdev/notice -->

Attributes declared with a source are parsed back out of the markup rather than stored in the comment, which keeps the JSON small and means editing the HTML by hand works. Anything not sourced is duplicated between the comment and the output, and the two drifting is what produces the block validation error. The design decision worth appreciating is that the content survives without the plugin — degraded, but present, which is not true of a shortcode.